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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [sw/] [rtems_driver/] [spwltest.c] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 jorisvr
/*
2
 * Test program for SpaceWire Light RTEMS driver.
3
 * Joris van Rantwijk, 2010.
4
 */
5
 
6
#include <stdlib.h>
7
#include <stdio.h>
8
#include <string.h>
9
#include <termios.h>
10
#include <rtems.h>
11
#include <rtems/error.h>
12
#include <bsp.h>
13
#include "spacewirelight.h"
14
 
15
void Init(rtems_task_argument);
16
 
17
#define CONFIGURE_INIT
18
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
19
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
20
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
21
#define CONFIGURE_INIT_TASK_ENTRY_POINT             Init
22
#define CONFIGURE_MAXIMUM_TASKS                     10
23
#define CONFIGURE_MAXIMUM_SEMAPHORES                10
24
#include <rtems/confdefs.h>
25
 
26
 
27
struct data_test_context {
28
    int queued;
29
    unsigned int rxpackets;
30
    unsigned int rxblocksize;
31
    unsigned int txpackets;
32
    unsigned int txpacketsize;
33
    unsigned int txblocksize;
34
    int verify;
35
    rtems_id semaphore;
36
    volatile unsigned int txdone_packets;
37
    volatile unsigned int rxdone_packets;
38
    volatile unsigned int rxdone_bytes;
39
    volatile unsigned int rxminsize;
40
    volatile unsigned int rxmaxsize;
41
    volatile int mismatch;
42
};
43
 
44
static spwl_handle      spwh;
45
static unsigned int     spw_index;
46
static struct spwl_options spw_opt = SPWL_OPTIONS_DEFAULT;
47
static spwl_linkmode    spw_mode;
48
 
49
#define MAX_BLOCK_SIZE 16384            /* do not change */
50
static unsigned char rxbuf[MAX_BLOCK_SIZE];
51
static unsigned char txpool[2*MAX_BLOCK_SIZE];
52
static spwl_txbuf_t  txbuf_desc[16];
53
 
54
static const unsigned int autotest_blocksize[] = {
55
    1, 101, 500, 2048, 4000, 0 };
56
static const unsigned int autotest_packetsize[] = {
57
    1, 2, 3, 4, 100, 101, 1000, 4096, 10000, 100000, 1000000, 0 };
58
 
59
/* Report error and stop program. */
60
static void fatal_error(const char *s, rtems_status_code err)
61
{
62
    fprintf(stderr, "ERROR: %s", s);
63
    if (err)
64
        fprintf(stderr, " (%s)", rtems_status_text(err));
65
    fprintf(stderr, "\n");
66
    rtems_shutdown_executive(1);
67
}
68
 
69
 
70
/* Wait for user to enter a string. */
71
static void get_string(char *buf, size_t maxlen)
72
{
73
    unsigned int i;
74
    int k;
75
    char c;
76
 
77
    i = strlen(buf);
78
    printf("%s", buf);
79
    fflush(stdout);
80
 
81
    while (1) {
82
        k = read(STDIN_FILENO, &c, 1);
83
        if (k != 1)
84
            fatal_error("read from console", 0);
85
        if (c == '\b' && i > 0) {
86
            i--;
87
            printf("\b \b");
88
            fflush(stdout);
89
        } else if (c == '\n' || c == '\r') {
90
            buf[i] = '\0';
91
            printf("\n");
92
            fflush(stdout);
93
            return;
94
        } else if (i + 1 < maxlen && c >= 32 && c < 127) {
95
            buf[i++] = c;
96
            printf("%c", c);
97
            fflush(stdout);
98
        }
99
    }
100
}
101
 
102
 
103
/* Wait for user to enter a non-negative number. */
104
static int get_num(const char *prompt, int low, int high, int deflt)
105
{
106
    char buf[20];
107
    char *p;
108
    unsigned long v;
109
 
110
    while (1) {
111
        printf("%s ", prompt);
112
        fflush(stdout);
113
 
114
        if (deflt >= 0)
115
            sprintf(buf, "%d", deflt);
116
        else
117
            buf[0] = '\0';
118
        get_string(buf, sizeof(buf));
119
 
120
        v = strtoul(buf, &p, 10);
121
        while (p != buf && *p == ' ')
122
            p++;
123
 
124
        if (p != buf && *p == '\0' && v >= low && v <= high)
125
            return v;
126
    }
127
}
128
 
129
 
130
/* Wait for user to enter an option index.
131
   Return entered number, or -1 if an empty string was entered. */
132
static int get_opt(int high)
133
{
134
    char buf[20];
135
    char *p;
136
    unsigned long v;
137
 
138
    while (1) {
139
        printf("Option (0 .. %d) ? ", high);
140
        fflush(stdout);
141
 
142
        buf[0] = '\0';
143
        get_string(buf, sizeof(buf));
144
 
145
        if (buf[0] == '\0')
146
            return -1;
147
 
148
        v = strtoul(buf, &p, 10);
149
        while (p != buf && *p == ' ')
150
            p++;
151
 
152
        if (p != buf && *p == '\0' && v <= high)
153
            return v;
154
    }
155
}
156
 
157
 
158
/* Set console to non-blocking. */
159
void set_nonblocking(int fd, struct termios *tcattr_orig)
160
{
161
    cc_t vmin_orig;
162
    tcgetattr(STDIN_FILENO, tcattr_orig);
163
    vmin_orig = tcattr_orig->c_cc[VMIN];
164
    tcattr_orig->c_cc[VMIN] = 0;
165
    tcsetattr(STDIN_FILENO, TCSANOW, tcattr_orig);
166
    tcattr_orig->c_cc[VMIN] = vmin_orig;
167
}
168
 
169
 
170
/* Open driver. */
171
void open_driver(void)
172
{
173
    rtems_status_code ret;
174
 
175
    printf("Opening driver for device index %u\n"
176
           "  options: rxbufs=%u, txbufs=%u, rxbufsize=%u, txbufsize=%u\n",
177
           spw_index,
178
           spw_opt.rxbufs, spw_opt.txbufs,
179
           spw_opt.rxbufsize, spw_opt.txbufsize);
180
 
181
    ret = spwl_open(&spwh, spw_index, &spw_opt);
182
    if (ret != RTEMS_SUCCESSFUL) {
183
        if (ret == RTEMS_INVALID_NUMBER)
184
            fprintf(stderr, "ERROR: SpaceWire Light core not found\n");
185
        fatal_error("spwl_open", ret);
186
    }
187
 
188
    spw_mode = SPWL_LINKMODE_NOP;
189
 
190
    printf("  ok\n");
191
}
192
 
193
 
194
/* Show current link mode and status. */
195
void show_status(void)
196
{
197
    spwl_linkstatus status;
198
    unsigned int speed;
199
 
200
    spwl_get_linkstatus(spwh, &status, NULL);
201
    speed = 100 * (spwl_get_default_linkspeed(spwh) + 1) / (spwl_get_linkspeed(spwh) + 1);
202
    printf("[ mode=%s,  status=%s,  speed=%u.%uMbit ]\n",
203
           ((spw_mode == SPWL_LINKMODE_START) ?     "start" :
204
            (spw_mode == SPWL_LINKMODE_AUTOSTART) ? "autostart" :
205
            (spw_mode == SPWL_LINKMODE_DISABLE) ?   "disable" : "nop"),
206
           ((status == SPWL_LINK_STARTED) ?    "started" :
207
            (status == SPWL_LINK_CONNECTING) ? "connecting" :
208
            (status == SPWL_LINK_RUN) ?        "RUN" : "off"),
209
           speed/10, speed%10);
210
}
211
 
212
 
213
/* Re-initialize driver. */
214
void do_init_driver(void)
215
{
216
    amba_apb_device apbdev;
217
    unsigned int i;
218
 
219
    printf("\n---- Re-initialize driver ----\n");
220
    printf("Closing driver\n");
221
    spwl_close(spwh);
222
 
223
    printf("Detected SpaceWire Light devices:\n");
224
    for (i = 0; ; i++) {
225
        if (!amba_find_next_apbslv(&amba_conf, VENDOR_OPENCORES, DEVICE_SPACEWIRELIGHT, &apbdev, i))
226
            break;
227
        printf(" index=%u, addr=0x%08x, irq=%u\n", i, apbdev.start, apbdev.irq);
228
    }
229
 
230
    spw_index = get_num("Enter index of device to open:", 0, 100, -1);
231
    spw_opt.rxbufs    = get_num("Number of RX buffers (min 0, max 4096):",
232
                                0, 4096, spw_opt.rxbufs);
233
    spw_opt.txbufs    = get_num("Number of TX buffers (min 0, max 4096):",
234
                                0, 4096, spw_opt.txbufs);
235
    spw_opt.rxbufsize = get_num("RX buffer size (bytes, min 32, max 16384):",
236
                                0, MAX_BLOCK_SIZE, spw_opt.rxbufsize);
237
    spw_opt.txbufsize = get_num("TX buffer size (bytes, min 32, max 16384):",
238
                                0, MAX_BLOCK_SIZE, spw_opt.txbufsize);
239
 
240
    open_driver();
241
}
242
 
243
 
244
/* Change link mode. */
245
void do_set_link_mode(void)
246
{
247
    rtems_status_code ret;
248
    int opt;
249
 
250
    printf("\n---- Change link mode ----\n");
251
    show_status();
252
    printf(" 1.  Start     - start link; restart link after error\n");
253
    printf(" 2.  Autostart - wait for remote activity before starting the link\n");
254
    printf(" 3.  Disable   - disable link\n");
255
    printf(" 4.  Nop       - keep current link status; do not restart after error\n");
256
 
257
    opt = get_opt(4);
258
    if (opt > 0) {
259
        printf("\n");
260
 
261
        switch (opt) {
262
            case 1:
263
                printf("Setting link mode = start\n");
264
                spw_mode = SPWL_LINKMODE_START;
265
                break;
266
            case 2:
267
                printf("Setting link mode = autostart\n");
268
                spw_mode = SPWL_LINKMODE_AUTOSTART;
269
                break;
270
            case 3:
271
                printf("Setting link mode = disable\n");
272
                spw_mode = SPWL_LINKMODE_DISABLE;
273
                break;
274
            case 4:
275
                printf("Setting link mode = nop\n");
276
                spw_mode = SPWL_LINKMODE_NOP;
277
                break;
278
        }
279
 
280
        ret = spwl_set_linkmode(spwh, spw_mode);
281
        if (ret != RTEMS_SUCCESSFUL)
282
            fatal_error("spwl_set_linkmode", ret);
283
        printf("  ok\n");
284
    }
285
}
286
 
287
 
288
/* Change link speed. */
289
void do_set_link_speed(void)
290
{
291
    char prompt[80];
292
    rtems_status_code ret;
293
    int maxspeed, speed, scaler, scaler10;
294
 
295
    printf("\n---- Change link speed ----\n");
296
 
297
    scaler10 = spwl_get_default_linkspeed(spwh);
298
    scaler = spwl_get_linkspeed(spwh);
299
    speed = (10 * (scaler10 + 1) + scaler / 2) / (scaler + 1);
300
    maxspeed = 10 * (scaler10 + 1);
301
 
302
    sprintf(prompt, "New link speed in Mbit/s (2 .. %d) ?", maxspeed);
303
    speed = get_num(prompt, 2, maxspeed, speed);
304
 
305
    scaler = (10 * (scaler10 + 1) + speed / 2) / speed - 1;
306
    if (scaler > 255)
307
        scaler = 255;
308
 
309
    speed = 100 * (scaler10 + 1) / (scaler + 1);
310
    printf("Setting speed = %d.%d Mbit/s, scaler = %d\n", speed/10, speed%10, scaler);
311
    ret = spwl_set_linkspeed(spwh, scaler);
312
    if (ret != RTEMS_SUCCESSFUL)
313
        fatal_error("spwl_set_linkmode", ret);
314
    printf("  ok\n");
315
}
316
 
317
 
318
/* RX/TX event loop. */
319
static int do_data_test_eventloop(struct data_test_context *ctx)
320
{
321
    rtems_status_code ret;
322
    unsigned int rxdone_packets = 0, rxdone_bytes = 0;
323
    unsigned int rxminsize = 0, rxmaxsize = 0;
324
    unsigned int txdone_packets = 0;
325
    unsigned int rxpos = 0, txpos = 0, txbufp = 0, txbufn = 0;
326
    unsigned int cond;
327
    unsigned int f, offset;
328
    void *buf;
329
    size_t p;
330
    int k;
331
    char c;
332
 
333
    /* Flush pending reclaimable buffers from previous test. */
334
    {
335
        spwl_txbuf_t *tmp;
336
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
337
            ;
338
    }
339
 
340
    /* Run until test completes or user aborts. */
341
    while (txdone_packets < ctx->txpackets ||
342
           rxdone_packets < ctx->rxpackets ||
343
           txbufn > 0) {
344
 
345
        /* Abort test when user hits Enter. */
346
        do {
347
            k = read(STDIN_FILENO, &c, 1);
348
        } while (k == 1 && c != '\n' && c != '\r');
349
        if (k == 1 && (c == '\n' || c == '\r'))
350
            return -1;
351
 
352
        /* Wait until progress can be made. */
353
        cond = 0;
354
        if (txbufn > 0)
355
            cond |= SPWL_COND_RECLAIM;
356
        if (ctx->queued && txdone_packets < ctx->txpackets && txbufn < 16)
357
            cond |= SPWL_COND_RDYSENDBUF;
358
        if (!ctx->queued && txdone_packets < ctx->txpackets)
359
            cond |= SPWL_COND_RDYSEND;
360
        if (rxdone_packets < ctx->rxpackets)
361
            cond |= SPWL_COND_RDYRECV;
362
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
363
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
364
            fatal_error("spwl_wait", ret);
365
 
366
        /* Send data. */
367
        if ((cond & (SPWL_COND_RDYSEND | SPWL_COND_RDYSENDBUF)) != 0) {
368
            if (((cond & SPWL_COND_RDYSEND) != 0 && ctx->queued) ||
369
                ((cond & SPWL_COND_RDYSENDBUF) != 0 && !ctx->queued) ||
370
                txbufn == 16 ||
371
                txdone_packets >= ctx->txpackets)
372
                fatal_error("spwl_wait, unexpected condition", 0);
373
            f = SPWL_EOP;
374
            p = ctx->txpacketsize - txpos;
375
            if (p > ctx->txblocksize) {
376
                p = ctx->txblocksize;
377
                f = 0;
378
            }
379
            offset = (txdone_packets * 4 + txpos) & (MAX_BLOCK_SIZE-1);
380
            if (ctx->queued) {
381
                txbuf_desc[txbufp].data = txpool + offset;
382
                txbuf_desc[txbufp].nbytes = p;
383
                txbuf_desc[txbufp].eop = f;
384
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
385
                if (ret != RTEMS_SUCCESSFUL)
386
                    fatal_error("spwl_send_txbuf", ret);
387
                txbufp = (txbufp + 1) & 15;
388
                txbufn++;
389
            } else {
390
                ret = spwl_send(spwh, txpool + offset, p, &p, f | SPWL_NO_WAIT);
391
                if (ret != RTEMS_SUCCESSFUL)
392
                    fatal_error("spwl_send", ret);
393
            }
394
            txpos += p;
395
            if (txpos >= ctx->txpacketsize) {
396
                txdone_packets++;
397
                txpos = 0;
398
            }
399
        }
400
 
401
        /* Receive data. */
402
        if ((cond & SPWL_COND_RDYRECV) != 0) {
403
            if (rxdone_packets >= ctx->rxpackets)
404
                fatal_error("spwl_wait, unexpected condition", 0);
405
            if (ctx->queued) {
406
                uint16_t nbytes;
407
                ret = spwl_recv_rxbuf(spwh, &buf, &nbytes, &f, SPWL_NO_WAIT);
408
                if (ret != RTEMS_SUCCESSFUL)
409
                    fatal_error("spwl_recv_rxbuf", ret);
410
                p = nbytes;
411
            } else {
412
                ret = spwl_recv(spwh, rxbuf, ctx->rxblocksize, &p, &f, SPWL_NO_WAIT);
413
                if (ret != RTEMS_SUCCESSFUL)
414
                    fatal_error("spwl_recv", ret);
415
                buf = rxbuf;
416
            }
417
            if (ctx->verify) {
418
                offset = (rxdone_packets * 4 + rxpos) & (MAX_BLOCK_SIZE-1);
419
                if (memcmp(buf, txpool + offset, p) != 0)
420
                    ctx->mismatch = 1;
421
            }
422
            rxpos += p;
423
            rxdone_bytes += p;
424
            if (f == SPWL_EEP || f == SPWL_EOP) {
425
                if (f == SPWL_EEP)
426
                    ctx->mismatch = 1;
427
                if (ctx->verify && rxpos > 0 && rxpos != ctx->txpacketsize)
428
                    ctx->mismatch = 1;
429
                if (rxpos > 0)
430
                    rxdone_packets++;
431
                if (rxpos > 0 && (rxpos < rxminsize || rxminsize == 0))
432
                    rxminsize = rxpos;
433
                if (rxpos > rxmaxsize)
434
                    rxmaxsize = rxpos;
435
                rxpos = 0;
436
            }
437
            if (ctx->queued) {
438
                ret = spwl_release_rxbuf(spwh, buf);
439
                if (ret != RTEMS_SUCCESSFUL)
440
                    fatal_error("spwl_release_rxbuf", ret);
441
            }
442
        }
443
 
444
        /* Reclaim TX buffers (queued mode). */
445
        if ((cond & SPWL_COND_RECLAIM) != 0) {
446
            spwl_txbuf_t *tmp;
447
            if (txbufn == 0)
448
                fatal_error("spwl_wait, unexpeced condition", 0);
449
            ret = spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT);
450
            if (ret != RTEMS_SUCCESSFUL)
451
                fatal_error("spwl_reclaim_txbuf", ret);
452
            txbufn--;
453
        }
454
 
455
        /* Update results. */
456
        ctx->txdone_packets = txdone_packets;
457
        ctx->rxdone_packets = rxdone_packets;
458
        ctx->rxdone_bytes   = rxdone_bytes;
459
        ctx->rxminsize      = rxminsize;
460
        ctx->rxmaxsize      = rxmaxsize;
461
    }
462
 
463
    return 0;
464
}
465
 
466
 
467
/* RX worker thread. */
468
static void rxtask_main(uintptr_t arg)
469
{
470
    struct data_test_context *ctx = (struct data_test_context *)arg;
471
    rtems_status_code ret;
472
    unsigned int rxdone_packets = 0, rxdone_bytes = 0;
473
    unsigned int rxminsize = 0, rxmaxsize = 0;
474
    unsigned int rxpos = 0;
475
    unsigned int f, offset;
476
    size_t p;
477
    void *buf;
478
 
479
    /* Receive data until test complete. */
480
    while (rxdone_packets < ctx->rxpackets) {
481
 
482
        if (ctx->queued) {
483
            uint16_t nbytes;
484
            ret = spwl_recv_rxbuf(spwh, &buf, &nbytes, &f, SPWL_WAIT);
485
            if (ret != RTEMS_SUCCESSFUL)
486
                fatal_error("spwl_recv_rxbuf", ret);
487
            p = nbytes;
488
        } else {
489
            ret = spwl_recv(spwh, rxbuf, ctx->rxblocksize, &p, &f, SPWL_WAIT);
490
            if (ret != RTEMS_SUCCESSFUL)
491
                fatal_error("spwl_recv", ret);
492
            buf = rxbuf;
493
        }
494
 
495
        if (ctx->verify) {
496
            offset = (rxdone_packets * 4 + rxpos) & (MAX_BLOCK_SIZE-1);
497
            if (memcmp(buf, txpool + offset, p) != 0)
498
                ctx->mismatch = 1;
499
        }
500
 
501
        rxpos += p;
502
        rxdone_bytes += p;
503
 
504
        if (f == SPWL_EEP || f == SPWL_EOP) {
505
            if (f == SPWL_EEP)
506
                ctx->mismatch = 1;
507
            if (ctx->verify && rxpos > 0 && rxpos != ctx->txpacketsize)
508
                ctx->mismatch = 1;
509
            if (rxpos > 0)
510
                rxdone_packets++;
511
            if (rxpos > 0 && (rxpos < rxminsize || rxminsize == 0))
512
                rxminsize = rxpos;
513
            if (rxpos > rxmaxsize)
514
                rxmaxsize = rxpos;
515
            rxpos = 0;
516
        }
517
 
518
        if (ctx->queued) {
519
            ret = spwl_release_rxbuf(spwh, buf);
520
            if (ret != RTEMS_SUCCESSFUL)
521
                fatal_error("spwl_release_rxbuf", ret);
522
        }
523
 
524
        /* Update results. */
525
        ctx->rxdone_packets = rxdone_packets;
526
        ctx->rxdone_bytes   = rxdone_bytes;
527
        ctx->rxminsize      = rxminsize;
528
        ctx->rxmaxsize      = rxmaxsize;
529
    }
530
 
531
    /* Release semaphore, then sleep forever. */
532
    rtems_semaphore_release(ctx->semaphore);
533
    rtems_task_suspend(RTEMS_SELF);
534
}
535
 
536
 
537
/* TX worker thread. */
538
static void txtask_main(uintptr_t arg)
539
{
540
    struct data_test_context *ctx = (struct data_test_context *)arg;
541
    rtems_status_code ret;
542
    unsigned int txdone_packets = 0;
543
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
544
    unsigned int f, offset;
545
    size_t p;
546
 
547
    /* Flush pending reclaimable buffers from previous test. */
548
    {
549
        spwl_txbuf_t *tmp;
550
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
551
            ;
552
    }
553
 
554
    /* Send data until test completes. */
555
    while (txdone_packets < ctx->txpackets || txbufn > 0) {
556
 
557
        /* Send data. */
558
        if (txdone_packets < ctx->txpackets && txbufn < 16) {
559
            f = SPWL_EOP;
560
            p = ctx->txpacketsize - txpos;
561
            if (p > ctx->txblocksize) {
562
                p = ctx->txblocksize;
563
                f = 0;
564
            }
565
            offset = (txdone_packets * 4 + txpos) & (MAX_BLOCK_SIZE-1);
566
            if (ctx->queued) {
567
                txbuf_desc[txbufp].data = txpool + offset;
568
                txbuf_desc[txbufp].nbytes = p;
569
                txbuf_desc[txbufp].eop = f;
570
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_WAIT);
571
                if (ret != RTEMS_SUCCESSFUL)
572
                    fatal_error("spwl_send_txbuf", ret);
573
                txbufp = (txbufp + 1) & 15;
574
                txbufn++;
575
            } else {
576
                ret = spwl_send(spwh, txpool + offset, p, &p, f | SPWL_WAIT);
577
                if (ret != RTEMS_SUCCESSFUL)
578
                    fatal_error("spwl_send", ret);
579
            }
580
            txpos += p;
581
            if (txpos >= ctx->txpacketsize) {
582
                txdone_packets++;
583
                txpos = 0;
584
            }
585
        }
586
 
587
        /* Reclaim TX buffers (queued mode). */
588
        if (ctx->queued && (txbufn == 16 || txdone_packets == ctx->txpackets)) {
589
            spwl_txbuf_t *tmp;
590
            ret = spwl_reclaim_txbuf(spwh, &tmp, SPWL_WAIT);
591
            if (ret != RTEMS_SUCCESSFUL)
592
                fatal_error("spwl_reclaim_txbuf", ret);
593
            if (tmp != txbuf_desc + ((16+txbufp-txbufn)&15))
594
                fatal_error("spwl_reclaim_txbuf returned unexpected pointer", 0);
595
            txbufn--;
596
        }
597
 
598
        /* Update results. */
599
        ctx->txdone_packets = txdone_packets;
600
    }
601
 
602
    /* Release semaphore, then sleep forever. */
603
    rtems_semaphore_release(ctx->semaphore);
604
    rtems_task_suspend(RTEMS_SELF);
605
}
606
 
607
 
608
/* Run a data send/receive test. Return 0 if ok, -1 if an error occurred. */
609
int do_data_test(int queued, int eventloop,
610
                 unsigned int rxpackets, unsigned int rxblocksize,
611
                 unsigned int txpackets, unsigned int txpacketsize,
612
                 unsigned int txblocksize, int verify)
613
{
614
    rtems_status_code ret;
615
    struct termios tcattr;
616
    struct data_test_context ctx;
617
    struct timespec tstart, tend;
618
    rtems_id rxtask = 0, txtask = 0;
619
    int aborted = 0;
620
    int activethreads;
621
    unsigned int elapsedms;
622
 
623
    if (queued && txpackets > 0 && (txblocksize & 3) != 0)
624
        fatal_error("invalid txblocksize in queued mode", 0);
625
 
626
    printf("\nStarting data test:\n");
627
    printf("  api:     %s, %s\n", queued ? "queue" : "copy",
628
                                  eventloop ? "eventloop" : "blocking");
629
    if (txpackets > 0) {
630
        printf("  send:    %u packets of %u bytes, blocksize=%u\n",
631
               txpackets, txpacketsize, txblocksize);
632
    }
633
    if (rxpackets > 0) {
634
        printf("  receive: %u packets", rxpackets);
635
        if (!queued)
636
            printf(", blocksize=%u", rxblocksize);
637
        printf(", verify=%s", verify ? "yes" : "no");
638
        printf("\n");
639
    }
640
 
641
    set_nonblocking(STDIN_FILENO, &tcattr);
642
    printf("  test started ... press Enter to abort\n");
643
 
644
    /* Set up context structure. */
645
    ctx.queued      = queued;
646
    ctx.rxpackets   = rxpackets;
647
    ctx.rxblocksize = rxblocksize;
648
    ctx.txpackets   = txpackets;
649
    ctx.txpacketsize = txpacketsize;
650
    ctx.txblocksize = txblocksize;
651
    ctx.verify      = verify;
652
    ctx.semaphore   = 0;
653
    ctx.txdone_packets = 0;
654
    ctx.rxdone_packets = 0;
655
    ctx.rxdone_bytes   = 0;
656
    ctx.rxminsize      = 0;
657
    ctx.rxmaxsize      = 0;
658
    ctx.mismatch       = 0;
659
 
660
    /* Create worker threads and completion semaphore for multi-thread test. */
661
    if (!eventloop) {
662
        ret = rtems_semaphore_create(rtems_build_name('d','o','n','e'),
663
                                     0,
664
                                     RTEMS_COUNTING_SEMAPHORE,
665
                                     RTEMS_NO_PRIORITY,
666
                                     &ctx.semaphore);
667
        if (ret != RTEMS_SUCCESSFUL)
668
            fatal_error("rtems_semaphore_create", ret);
669
        if (rxpackets > 0) {
670
            ret = rtems_task_create(rtems_build_name('r','x','t','s'),
671
                                    200,
672
                                    RTEMS_CONFIGURED_MINIMUM_STACK_SIZE,
673
                                    RTEMS_PREEMPT,
674
                                    RTEMS_NO_FLOATING_POINT,
675
                                    &rxtask);
676
            if (ret != RTEMS_SUCCESSFUL)
677
                fatal_error("rtems_task_create", ret);
678
        }
679
        if (txpackets > 0) {
680
            ret = rtems_task_create(rtems_build_name('t','x','t','s'),
681
                                    200,
682
                                    RTEMS_CONFIGURED_MINIMUM_STACK_SIZE,
683
                                    RTEMS_PREEMPT | RTEMS_NO_TIMESLICE,
684
                                    RTEMS_LOCAL,
685
                                    &txtask);
686
            if (ret != RTEMS_SUCCESSFUL)
687
                fatal_error("rtems_task_create", ret);
688
        }
689
    }
690
 
691
    /* Start timer. */
692
    rtems_clock_get_uptime(&tstart);
693
 
694
    /* Run test. */
695
    if (eventloop) {
696
 
697
        if (do_data_test_eventloop(&ctx) != 0)
698
            aborted = 1;
699
 
700
    } else {
701
 
702
        /* Start worker threads. */
703
        if (rxpackets > 0)
704
            rtems_task_start(rxtask, rxtask_main, (uintptr_t)&ctx);
705
        if (txpackets > 0)
706
            rtems_task_start(txtask, txtask_main, (uintptr_t)&ctx);
707
 
708
        /* Wait until test complete or test aborted. */
709
        activethreads = (rxpackets > 0) + (txpackets > 0);
710
        while (activethreads) {
711
            int k;
712
            char c;
713
 
714
            /* Abort test when user hits Enter. */
715
            do {
716
                k = read(STDIN_FILENO, &c, 1);
717
            } while (k == 1 && c != '\n' && c != '\r');
718
            if (k == 1 && (c == '\n' || c == '\r')) {
719
                aborted = 1;
720
                break;
721
            }
722
 
723
            ret = rtems_semaphore_obtain(ctx.semaphore, RTEMS_WAIT,
724
                                         rtems_clock_get_ticks_per_second());
725
            if (ret == RTEMS_SUCCESSFUL)
726
                activethreads--;
727
        }
728
 
729
    }
730
 
731
    /* Stop timer. */
732
    rtems_clock_get_uptime(&tend);
733
 
734
    /* Clean up resources. */
735
    if (!eventloop) {
736
        if (rxpackets > 0)
737
            rtems_task_delete(rxtask);
738
        if (txpackets > 0)
739
            rtems_task_delete(txtask);
740
        rtems_semaphore_delete(ctx.semaphore);
741
    }
742
 
743
    /* Report result. */
744
    if (aborted)
745
        printf("  aborted, ");
746
    else
747
        printf("  done, ");
748
 
749
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
750
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
751
    printf("%3d.%03d seconds elapsed\n", elapsedms / 1000, elapsedms % 1000);
752
    if (txpackets > 0) {
753
        uint64_t rate = (uint64_t)ctx.txdone_packets * (uint64_t)txpacketsize * 1000U / elapsedms;
754
        printf("  sent %u packets (%u bytes/s)\n",
755
               ctx.txdone_packets, (unsigned int)rate);
756
    }
757
    if (rxpackets > 0) {
758
        uint64_t rate = (uint64_t)ctx.rxdone_bytes * 1000U / elapsedms;
759
        printf("  received %u packets, %u bytes (%u bytes/s)\n",
760
               ctx.rxdone_packets, ctx.rxdone_bytes, (unsigned int)rate);
761
        if (ctx.rxdone_packets > 0)
762
            printf("  received min packet size = %u, max packet size = %u\n",
763
                   ctx.rxminsize, ctx.rxmaxsize);
764
    }
765
    if (ctx.mismatch)
766
        printf("  MISMATCH OR EEP DETECTED IN RECEIVED DATA\n");
767
 
768
    /* Restore stdin mode. */
769
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
770
 
771
    return (aborted || ctx.mismatch) ? -1 : 0;
772
}
773
 
774
 
775
/* Run a series of loopback tests. */
776
int do_autotest(int verify)
777
{
778
    int queued, eventloop;
779
    unsigned int npackets, packetsize, rxblocksize, txblocksize;
780
    int i, j, ret;
781
 
782
    printf("\nStarting automatic test\n");
783
 
784
    for (queued = 0; queued <= 1; queued++) {
785
        for(eventloop = 0; eventloop <= 1; eventloop++) {
786
            for (i = 0; autotest_packetsize[i] > 0; i++) {
787
                for (j = 0; autotest_blocksize[j] > 0; j++) {
788
 
789
                    packetsize = autotest_packetsize[i];
790
                    txblocksize = autotest_blocksize[j];
791
 
792
                    if (queued && (txblocksize & 3) != 0)
793
                        continue;
794
 
795
                    npackets = 10000000 / packetsize;
796
                    if (npackets > 100000)
797
                        npackets = 100000;
798
                    if (npackets * packetsize / txblocksize > 100000)
799
                        npackets = 100000 * txblocksize / packetsize;
800
                    if (npackets < 1)
801
                        continue;
802
 
803
                    rxblocksize = 4000;
804
                    ret = do_data_test(queued, eventloop,
805
                                       npackets, rxblocksize,
806
                                       npackets, packetsize, txblocksize,
807
                                       verify);
808
                    if (ret < 0)
809
                        return ret;
810
 
811
                    if (!queued && autotest_blocksize[j] != 4000) {
812
                        txblocksize = 4000;
813
                        rxblocksize = autotest_blocksize[j];
814
                        ret = do_data_test(queued, eventloop,
815
                                           npackets, rxblocksize,
816
                                           npackets, packetsize, txblocksize,
817
                                           verify);
818
                        if (ret < 0)
819
                            return ret;
820
                    }
821
 
822 9 jorisvr
                    if (txblocksize > packetsize && rxblocksize > packetsize)
823
                        break;
824 6 jorisvr
                }
825
            }
826
        }
827
    }
828
 
829
    printf("\nAutomatic test completed\n");
830
    return 0;
831
}
832
 
833
 
834
/* Put system in passive loopback mode. */
835
void do_passive_loopback(int queued, int blocksize)
836
{
837
    rtems_status_code ret;
838
    struct termios tcattr;
839
    struct timespec tstart, tend;
840
    unsigned int done_packets = 0, done_bytes = 0;
841
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
842
    size_t rxlen = 0;
843
    unsigned int rxeop = 0;
844
    void *rxbufp;
845
    unsigned int cond;
846
    int k;
847
    char c;
848
    unsigned int elapsedms;
849
    uint64_t rate;
850
 
851
    printf("\nStarting passive loopback mode:\n");
852
    printf("  api:       %s\n", queued ? "queue" : "copy");
853
    if (!queued)
854
        printf("  blocksize: %u\n", blocksize);
855
 
856
    set_nonblocking(STDIN_FILENO, &tcattr);
857
    printf("  started ... press Enter to stop\n");
858
 
859
    /* Flush pending reclaimable buffers from previous test. */
860
    {
861
        spwl_txbuf_t *tmp;
862
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
863
            ;
864
    }
865
 
866
    /* Start timer. */
867
    rtems_clock_get_uptime(&tstart);
868
 
869
    /* Run in passive loopback. */
870
    while (1) {
871
 
872
        /* Check if user pressed Enter. */
873
        do {
874
            k = read(STDIN_FILENO, &c, 1);
875
        } while (k == 1 && c != '\n' && c != '\r');
876
        if (k == 1 && (c == '\n' || c == '\r'))
877
            break;
878
 
879
        /* Receive data. */
880
        if (rxlen == 0 && rxeop == 0) {
881
            if (queued) {
882
                uint16_t rxlen16;
883
                ret = spwl_recv_rxbuf(spwh, &rxbufp, &rxlen16, &rxeop, SPWL_NO_WAIT);
884
                rxlen = rxlen16;
885
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
886
                    fatal_error("spwl_recv_rxbuf", ret);
887
            } else {
888
                ret = spwl_recv(spwh, rxbuf, blocksize, &rxlen, &rxeop, SPWL_NO_WAIT);
889
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
890
                    fatal_error("spwl_recv", ret);
891
            }
892
            done_bytes += rxlen;
893
            if (rxeop)
894
                done_packets++;
895
        }
896
 
897
        /* Send data. */
898
        if ((rxlen > 0 || rxeop != 0) && txbufn < 16) {
899
            if (queued) {
900
                txbuf_desc[txbufp].data = rxbufp;
901
                txbuf_desc[txbufp].nbytes = rxlen;
902
                txbuf_desc[txbufp].eop = rxeop;
903
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
904
                if (ret == RTEMS_SUCCESSFUL) {
905
                    ret = spwl_release_rxbuf(spwh, rxbufp);
906
                    if (ret != RTEMS_SUCCESSFUL)
907
                        fatal_error("spwl_release_rxbuf", ret);
908
                    rxlen = rxeop = 0;
909
                    txbufp = (txbufp + 1) & 15;
910
                    txbufn++;
911
                }
912
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
913
                    fatal_error("spwl_send_txbuf", ret);
914
            } else {
915
                size_t ntrans;
916
                ret = spwl_send(spwh, rxbuf + txpos, rxlen - txpos, &ntrans, rxeop | SPWL_NO_WAIT);
917
                if (ret == RTEMS_SUCCESSFUL) {
918
                    txpos += ntrans;
919
                    if (txpos == rxlen)
920
                        rxlen = rxeop = txpos = 0;
921
                }
922
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
923
                    fatal_error("spwl_send", ret);
924
            }
925
        }
926
 
927
        /* Reclaim buffers. */
928
        if (txbufn > 0) {
929
            struct spwl_txbuf *p;
930
            ret = spwl_reclaim_txbuf(spwh, &p, SPWL_NO_WAIT);
931
            if (ret == RTEMS_SUCCESSFUL) {
932
                if (p != txbuf_desc + ((txbufp + 16 - txbufn) & 15))
933
                    fatal_error("spwl_reclaim_txbuf returned unexpected buffer", 0);
934
                txbufn--;
935
            }
936
            if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
937
                fatal_error("spwl_reclaim_txbuf", ret);
938
        }
939
 
940
        /* Wait until ready. */
941
        cond = 0;
942
        if (rxlen == 0 && rxeop == 0)
943
            cond |= SPWL_COND_RDYRECV;
944
        if (!queued && (rxlen > 0 || rxeop != 0))
945
            cond |= SPWL_COND_RDYSEND;
946
        if (queued && (rxlen > 0 || rxeop != 0) && txbufn < 16)
947
            cond |= SPWL_COND_RDYSENDBUF;
948
        if (txbufn > 0)
949
            cond |= SPWL_COND_RECLAIM;
950
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
951
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
952
            fatal_error("spwl_wait", ret);
953
    }
954
 
955
    /* Stop timer. */
956
    rtems_clock_get_uptime(&tend);
957
 
958
    /* Report result. */
959
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
960
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
961
    printf("  done, %3d.%03d seconds elapsed\n",
962
           elapsedms / 1000, elapsedms % 1000);
963
    rate = (uint64_t)done_bytes * 1000U / elapsedms;
964
    printf("  sent %u packets, %u bytes (%u bytes/s)\n",
965
           done_packets, done_bytes, (unsigned int)rate);
966
 
967
    /* Restore stdin mode. */
968
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
969
}
970
 
971
 
972
/* Send time codes. */
973
void do_send_timecode(void)
974
{
975
    rtems_status_code ret;
976
    uint8_t timecode;
977
    int value;
978
 
979
    printf("\n");
980
    value = get_num("Enter timecode value to send (0 .. 63):", 0, 63, -1);
981
    if (value >= 0) {
982
        timecode = spwl_get_timecode(spwh);
983
        printf("Last received timecode value: %u\n", timecode);
984
        printf("Sending timecode value %d\n", value);
985
        ret = spwl_send_timecode(spwh, value);
986
        if (ret != RTEMS_SUCCESSFUL)
987
            fatal_error("spwl_send_timecode", ret);
988
        timecode = spwl_get_timecode(spwh);
989
        printf("Last received timecode value: %u\n", timecode);
990
        rtems_task_wake_after(rtems_clock_get_ticks_per_second() / 10);
991
        timecode = spwl_get_timecode(spwh);
992
        printf("Last received timecode value (after 0.1s): %u\n", timecode);
993
    }
994
}
995
 
996
 
997
/* Show time codes and link events. */
998
void do_recv_timecode(void)
999
{
1000
    rtems_status_code ret;
1001
    struct termios tcattr;
1002
    struct timespec tstart, ts;
1003
    spwl_linkstatus status;
1004
    int link_is_up;
1005
    unsigned int errors;
1006
    unsigned int cond;
1007
    unsigned int millis;
1008
    uint8_t timecode;
1009
    int k;
1010
    char c;
1011
 
1012
    printf("\n---- Show time codes and link events ----\n");
1013
 
1014
    rtems_clock_get_uptime(&tstart);
1015
 
1016
    spwl_get_linkstatus(spwh, &status, &errors);
1017
    link_is_up = (status == SPWL_LINK_RUN);
1018
    printf("  link %s, errors = %s%s%s%s%s%s\n",
1019
           link_is_up ? "up" : "down",
1020
           (errors == 0) ? "none" : "",
1021
           (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
1022
           (errors & SPWL_ERR_PARITY)     ? "parity " : "",
1023
           (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
1024
           (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
1025
           (errors & SPWL_ERR_AHB)        ? "AHB " : "");
1026
 
1027
    timecode = spwl_get_timecode(spwh);
1028
    printf("  last timecode = %u\n", timecode);
1029
 
1030
    set_nonblocking(STDIN_FILENO, &tcattr);
1031
    printf("  waiting for events ... press Enter to stop\n");
1032
 
1033
    while (1) {
1034
 
1035
        /* Abort test when user hits Enter. */
1036
        do {
1037
            k = read(STDIN_FILENO, &c, 1);
1038
        } while (k == 1 && c != '\n' && c != '\r');
1039
        if (k == 1 && (c == '\n' || c == '\r'))
1040
            break;
1041
 
1042
        /* Wait for event. */
1043
        cond = SPWL_COND_TIMECODE;
1044
        if (link_is_up)
1045
            cond |= SPWL_COND_LINKDOWN;
1046
        else
1047
            cond |= SPWL_COND_LINKUP;
1048
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
1049
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
1050
            fatal_error("spwl_wait", ret);
1051
 
1052
        /* Report event. */
1053
        rtems_clock_get_uptime(&ts);
1054
        millis = (ts.tv_sec - tstart.tv_sec) * 1000 +
1055
                 ts.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
1056
 
1057
        if ((cond & SPWL_COND_LINKUP) != 0) {
1058
            printf("  %4u.%03u: link up\n", millis / 1000, millis % 1000);
1059
            link_is_up = 1;
1060
        }
1061
 
1062
        if ((cond & SPWL_COND_LINKDOWN) != 0) {
1063
            spwl_get_linkstatus(spwh, &status, &errors);
1064
            printf("  %4u.%03u: link down, errors = %s%s%s%s%s%s\n",
1065
                   millis / 1000, millis % 1000,
1066
                   (errors == 0) ? "none" : "",
1067
                   (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
1068
                   (errors & SPWL_ERR_PARITY)     ? "parity " : "",
1069
                   (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
1070
                   (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
1071
                   (errors & SPWL_ERR_AHB)        ? "AHB " : "");
1072
            link_is_up = 0;
1073
        }
1074
 
1075
        if ((cond & SPWL_COND_TIMECODE) != 0) {
1076
            timecode = spwl_get_timecode(spwh);
1077
            printf("  %4u.%03u: got tick, timecode = %d\n",
1078
                   millis / 1000, millis % 1000, timecode);
1079
        }
1080
    }
1081
 
1082
    /* Restore console mode. */
1083
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
1084
 
1085
    printf("  done\n");
1086
}
1087
 
1088
 
1089
/* Receive/send menu. */
1090
void menu_recvsend(int send)
1091
{
1092
    int opt;
1093
    int queued, eventloop;
1094
    int npacket, packetsize, blocksize;
1095
 
1096
    do {
1097
 
1098
        printf("\n---- %s packets ----\n", send ? "Send" : "Receive");
1099
        show_status();
1100
        printf(" 1.  Copy API; blocking calls\n");
1101
        printf(" 2.  Copy API; event loop\n");
1102
        printf(" 3.  Queue API; blocking calls\n");
1103
        printf(" 4.  Queue API; event loop\n");
1104
        printf(" 0.  Back to main menu\n");
1105
 
1106
        opt = get_opt(4);
1107
        if (opt > 0 && opt <= 4) {
1108
 
1109
            queued    = (opt == 3 || opt == 4);
1110
            eventloop = (opt == 2 || opt == 4);
1111
 
1112
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
1113
 
1114
            if (send)
1115
                packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
1116
            else
1117
                packetsize = 0;
1118
 
1119
            blocksize = 0;
1120
            while (send || !queued) {
1121 9 jorisvr
                blocksize = get_num("Block size in bytes (1 .. 16384) ?", 1, MAX_BLOCK_SIZE, 4096);
1122 6 jorisvr
                if ((blocksize & 3) == 0 || !queued)
1123
                    break;
1124
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
1125
            }
1126
 
1127
            if (npacket > 0) {
1128
                if (send) {
1129
                    do_data_test(queued, eventloop,
1130
                                 0, 0,
1131
                                 npacket, packetsize, blocksize,
1132
                                 0);
1133
                } else {
1134
                    do_data_test(queued, eventloop,
1135
                                 npacket, blocksize,
1136
                                 0, 0, 0,
1137
                                 0);
1138
                }
1139
            }
1140
        }
1141
    } while (opt != 0);
1142
}
1143
 
1144
 
1145
/* Loopback test menu. */
1146
void menu_loopback(int verify)
1147
{
1148
    int opt;
1149
    int queued, eventloop;
1150
    int npacket, packetsize, blocksize;
1151
 
1152
    do {
1153
 
1154
        printf("\n---- Loopback test %s ----\n",
1155
               verify ? "with data compare" : "(no compare)");
1156
        show_status();
1157
        printf(" 1.  Copy API; blocking calls; multi-threaded\n");
1158
        printf(" 2.  Copy API; event loop\n");
1159
        printf(" 3.  Queue API; blocking calls; multi-threaded\n");
1160
        printf(" 4.  Queue API; event loop\n");
1161
        printf(" 5.  Automatic test\n");
1162
        printf(" 0.  Back to main menu\n");
1163
 
1164
        opt = get_opt(5);
1165
        if (opt > 0 && opt <= 4) {
1166
 
1167
            queued    = (opt == 3 || opt == 4);
1168
            eventloop = (opt == 2 || opt == 4);
1169
 
1170
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
1171
            packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
1172
            while (1) {
1173 9 jorisvr
                blocksize = get_num("Block size in bytes (1 .. 16384) ?", 1, MAX_BLOCK_SIZE, 4096);
1174 6 jorisvr
                if ((blocksize & 3) == 0 || !queued)
1175
                    break;
1176
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
1177
            }
1178
 
1179
            if (npacket > 0) {
1180
                do_data_test(queued, eventloop,
1181
                             npacket, blocksize,
1182
                             npacket, packetsize, blocksize,
1183
                             verify);
1184
            }
1185
 
1186
        } else if (opt == 5) {
1187
 
1188
            do_autotest(verify);
1189
 
1190
        }
1191
 
1192
    } while (opt != 0);
1193
}
1194
 
1195
 
1196
/* Passive loopback menu. */
1197
void menu_passiveloop(void)
1198
{
1199
    int opt;
1200
    int queued, blocksize = 0;
1201
 
1202
    printf("\n---- Passive loopback mode----\n");
1203
    show_status();
1204
    printf(" 1.  Copy API\n");
1205
    printf(" 2.  Queue API\n");
1206
    printf(" 0.  Back to main menu\n");
1207
 
1208
    opt = get_opt(2);
1209
    if (opt > 0 && opt <= 2) {
1210
 
1211
        queued = (opt == 2);
1212
 
1213
        while (!queued) {
1214
            blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
1215
            if ((blocksize & 3) == 0 || !queued)
1216
                break;
1217
            printf("INVALID: block size must be a multiple of 4 in queued mode\n");
1218
        }
1219
 
1220
        do_passive_loopback(queued, blocksize);
1221
    }
1222
}
1223
 
1224
 
1225
/* Main menu. */
1226
void menu_main(void)
1227
{
1228
    int opt;
1229
 
1230
    do {
1231
        printf("\n==== SpaceWire Light Test ====\n");
1232
        show_status();
1233
        printf(" 1.  Re-initialize driver\n");
1234
        printf(" 2.  Set link mode\n");
1235
        printf(" 3.  Set link speed\n");
1236
        printf(" 4.  Receive packets\n");
1237
        printf(" 5.  Send packets\n");
1238
        printf(" 6.  Loopback test (no compare)\n");
1239
        printf(" 7.  Loopback test with data compare\n");
1240
        printf(" 8.  Passive loopback\n");
1241
        printf(" 9.  Send time code\n");
1242
        printf("10.  Show time codes and link events\n");
1243
        printf(" 0.  Exit\n");
1244
 
1245
        opt = get_opt(10);
1246
        switch (opt) {
1247
            case 1: do_init_driver(); break;
1248
            case 2: do_set_link_mode(); break;
1249
            case 3: do_set_link_speed(); break;
1250
            case 4: menu_recvsend(0); break;
1251
            case 5: menu_recvsend(1); break;
1252
            case 6: menu_loopback(0); break;
1253
            case 7: menu_loopback(1); break;
1254
            case 8: menu_passiveloop(); break;
1255
            case 9: do_send_timecode(); break;
1256
            case 10: do_recv_timecode(); break;
1257
        }
1258
 
1259
    } while (opt != 0);
1260
}
1261
 
1262
 
1263
/* Main program. */
1264
void Init(rtems_task_argument arg)
1265
{
1266
    int i;
1267
 
1268
    printf("\nSpaceWire Light test program for RTEMS\n\n");
1269
 
1270
    /* Put stdin in raw mode. */
1271
    {
1272
        struct termios tcattr;
1273
        tcgetattr(STDIN_FILENO, &tcattr);
1274
        tcattr.c_iflag &= ~IGNCR;
1275
        tcattr.c_lflag &= ~(ICANON | ECHO);
1276
        tcattr.c_cc[VMIN] = 1;
1277
        tcattr.c_cc[VTIME] = 0;
1278
        tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
1279
    }
1280
 
1281
    /* Create TX data pool. */
1282
    for (i = 0; i < MAX_BLOCK_SIZE; i++) {
1283
        int v = ((i & 1) << 7) | ((i & 2) << 5) |
1284
                ((i & 4) << 3) | ((i & 8) << 1) |
1285
                ((i & 16) >> 1) | ((i & 32) >> 3) |
1286
                ((i & 64) >> 5) | ((i & 128) >> 7);
1287
        v += (i >> 8);
1288
        txpool[i] = v;
1289
    }
1290
    memcpy(txpool + MAX_BLOCK_SIZE, txpool, MAX_BLOCK_SIZE);
1291
 
1292
    /* Open SpaceWire core */
1293
    spw_index = 0;
1294
    open_driver();
1295
 
1296
    /* Main menu. */
1297
    menu_main();
1298
 
1299
    /* Clean up. */
1300
    spwl_close(spwh);
1301
 
1302
    printf("\nExit.\n");
1303
    rtems_shutdown_executive(0);
1304
}
1305
 
1306
/* vim: expandtab softtabstop=4
1307
*/
1308
/* end */

powered by: WebSVN 2.1.0

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