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 6

Go to most recent revision | 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
                }
823
            }
824
        }
825
    }
826
 
827
    printf("\nAutomatic test completed\n");
828
    return 0;
829
}
830
 
831
 
832
/* Put system in passive loopback mode. */
833
void do_passive_loopback(int queued, int blocksize)
834
{
835
    rtems_status_code ret;
836
    struct termios tcattr;
837
    struct timespec tstart, tend;
838
    unsigned int done_packets = 0, done_bytes = 0;
839
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
840
    size_t rxlen = 0;
841
    unsigned int rxeop = 0;
842
    void *rxbufp;
843
    unsigned int cond;
844
    int k;
845
    char c;
846
    unsigned int elapsedms;
847
    uint64_t rate;
848
 
849
    printf("\nStarting passive loopback mode:\n");
850
    printf("  api:       %s\n", queued ? "queue" : "copy");
851
    if (!queued)
852
        printf("  blocksize: %u\n", blocksize);
853
 
854
    set_nonblocking(STDIN_FILENO, &tcattr);
855
    printf("  started ... press Enter to stop\n");
856
 
857
    /* Flush pending reclaimable buffers from previous test. */
858
    {
859
        spwl_txbuf_t *tmp;
860
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
861
            ;
862
    }
863
 
864
    /* Start timer. */
865
    rtems_clock_get_uptime(&tstart);
866
 
867
    /* Run in passive loopback. */
868
    while (1) {
869
 
870
        /* Check if user pressed Enter. */
871
        do {
872
            k = read(STDIN_FILENO, &c, 1);
873
        } while (k == 1 && c != '\n' && c != '\r');
874
        if (k == 1 && (c == '\n' || c == '\r'))
875
            break;
876
 
877
        /* Receive data. */
878
        if (rxlen == 0 && rxeop == 0) {
879
            if (queued) {
880
                uint16_t rxlen16;
881
                ret = spwl_recv_rxbuf(spwh, &rxbufp, &rxlen16, &rxeop, SPWL_NO_WAIT);
882
                rxlen = rxlen16;
883
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
884
                    fatal_error("spwl_recv_rxbuf", ret);
885
            } else {
886
                ret = spwl_recv(spwh, rxbuf, blocksize, &rxlen, &rxeop, SPWL_NO_WAIT);
887
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
888
                    fatal_error("spwl_recv", ret);
889
            }
890
            done_bytes += rxlen;
891
            if (rxeop)
892
                done_packets++;
893
        }
894
 
895
        /* Send data. */
896
        if ((rxlen > 0 || rxeop != 0) && txbufn < 16) {
897
            if (queued) {
898
                txbuf_desc[txbufp].data = rxbufp;
899
                txbuf_desc[txbufp].nbytes = rxlen;
900
                txbuf_desc[txbufp].eop = rxeop;
901
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
902
                if (ret == RTEMS_SUCCESSFUL) {
903
                    ret = spwl_release_rxbuf(spwh, rxbufp);
904
                    if (ret != RTEMS_SUCCESSFUL)
905
                        fatal_error("spwl_release_rxbuf", ret);
906
                    rxlen = rxeop = 0;
907
                    txbufp = (txbufp + 1) & 15;
908
                    txbufn++;
909
                }
910
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
911
                    fatal_error("spwl_send_txbuf", ret);
912
            } else {
913
                size_t ntrans;
914
                ret = spwl_send(spwh, rxbuf + txpos, rxlen - txpos, &ntrans, rxeop | SPWL_NO_WAIT);
915
                if (ret == RTEMS_SUCCESSFUL) {
916
                    txpos += ntrans;
917
                    if (txpos == rxlen)
918
                        rxlen = rxeop = txpos = 0;
919
                }
920
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
921
                    fatal_error("spwl_send", ret);
922
            }
923
        }
924
 
925
        /* Reclaim buffers. */
926
        if (txbufn > 0) {
927
            struct spwl_txbuf *p;
928
            ret = spwl_reclaim_txbuf(spwh, &p, SPWL_NO_WAIT);
929
            if (ret == RTEMS_SUCCESSFUL) {
930
                if (p != txbuf_desc + ((txbufp + 16 - txbufn) & 15))
931
                    fatal_error("spwl_reclaim_txbuf returned unexpected buffer", 0);
932
                txbufn--;
933
            }
934
            if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
935
                fatal_error("spwl_reclaim_txbuf", ret);
936
        }
937
 
938
        /* Wait until ready. */
939
        cond = 0;
940
        if (rxlen == 0 && rxeop == 0)
941
            cond |= SPWL_COND_RDYRECV;
942
        if (!queued && (rxlen > 0 || rxeop != 0))
943
            cond |= SPWL_COND_RDYSEND;
944
        if (queued && (rxlen > 0 || rxeop != 0) && txbufn < 16)
945
            cond |= SPWL_COND_RDYSENDBUF;
946
        if (txbufn > 0)
947
            cond |= SPWL_COND_RECLAIM;
948
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
949
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
950
            fatal_error("spwl_wait", ret);
951
    }
952
 
953
    /* Stop timer. */
954
    rtems_clock_get_uptime(&tend);
955
 
956
    /* Report result. */
957
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
958
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
959
    printf("  done, %3d.%03d seconds elapsed\n",
960
           elapsedms / 1000, elapsedms % 1000);
961
    rate = (uint64_t)done_bytes * 1000U / elapsedms;
962
    printf("  sent %u packets, %u bytes (%u bytes/s)\n",
963
           done_packets, done_bytes, (unsigned int)rate);
964
 
965
    /* Restore stdin mode. */
966
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
967
}
968
 
969
 
970
/* Send time codes. */
971
void do_send_timecode(void)
972
{
973
    rtems_status_code ret;
974
    uint8_t timecode;
975
    int value;
976
 
977
    printf("\n");
978
    value = get_num("Enter timecode value to send (0 .. 63):", 0, 63, -1);
979
    if (value >= 0) {
980
        timecode = spwl_get_timecode(spwh);
981
        printf("Last received timecode value: %u\n", timecode);
982
        printf("Sending timecode value %d\n", value);
983
        ret = spwl_send_timecode(spwh, value);
984
        if (ret != RTEMS_SUCCESSFUL)
985
            fatal_error("spwl_send_timecode", ret);
986
        timecode = spwl_get_timecode(spwh);
987
        printf("Last received timecode value: %u\n", timecode);
988
        rtems_task_wake_after(rtems_clock_get_ticks_per_second() / 10);
989
        timecode = spwl_get_timecode(spwh);
990
        printf("Last received timecode value (after 0.1s): %u\n", timecode);
991
    }
992
}
993
 
994
 
995
/* Show time codes and link events. */
996
void do_recv_timecode(void)
997
{
998
    rtems_status_code ret;
999
    struct termios tcattr;
1000
    struct timespec tstart, ts;
1001
    spwl_linkstatus status;
1002
    int link_is_up;
1003
    unsigned int errors;
1004
    unsigned int cond;
1005
    unsigned int millis;
1006
    uint8_t timecode;
1007
    int k;
1008
    char c;
1009
 
1010
    printf("\n---- Show time codes and link events ----\n");
1011
 
1012
    rtems_clock_get_uptime(&tstart);
1013
 
1014
    spwl_get_linkstatus(spwh, &status, &errors);
1015
    link_is_up = (status == SPWL_LINK_RUN);
1016
    printf("  link %s, errors = %s%s%s%s%s%s\n",
1017
           link_is_up ? "up" : "down",
1018
           (errors == 0) ? "none" : "",
1019
           (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
1020
           (errors & SPWL_ERR_PARITY)     ? "parity " : "",
1021
           (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
1022
           (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
1023
           (errors & SPWL_ERR_AHB)        ? "AHB " : "");
1024
 
1025
    timecode = spwl_get_timecode(spwh);
1026
    printf("  last timecode = %u\n", timecode);
1027
 
1028
    set_nonblocking(STDIN_FILENO, &tcattr);
1029
    printf("  waiting for events ... press Enter to stop\n");
1030
 
1031
    while (1) {
1032
 
1033
        /* Abort test when user hits Enter. */
1034
        do {
1035
            k = read(STDIN_FILENO, &c, 1);
1036
        } while (k == 1 && c != '\n' && c != '\r');
1037
        if (k == 1 && (c == '\n' || c == '\r'))
1038
            break;
1039
 
1040
        /* Wait for event. */
1041
        cond = SPWL_COND_TIMECODE;
1042
        if (link_is_up)
1043
            cond |= SPWL_COND_LINKDOWN;
1044
        else
1045
            cond |= SPWL_COND_LINKUP;
1046
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
1047
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
1048
            fatal_error("spwl_wait", ret);
1049
 
1050
        /* Report event. */
1051
        rtems_clock_get_uptime(&ts);
1052
        millis = (ts.tv_sec - tstart.tv_sec) * 1000 +
1053
                 ts.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
1054
 
1055
        if ((cond & SPWL_COND_LINKUP) != 0) {
1056
            printf("  %4u.%03u: link up\n", millis / 1000, millis % 1000);
1057
            link_is_up = 1;
1058
        }
1059
 
1060
        if ((cond & SPWL_COND_LINKDOWN) != 0) {
1061
            spwl_get_linkstatus(spwh, &status, &errors);
1062
            printf("  %4u.%03u: link down, errors = %s%s%s%s%s%s\n",
1063
                   millis / 1000, millis % 1000,
1064
                   (errors == 0) ? "none" : "",
1065
                   (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
1066
                   (errors & SPWL_ERR_PARITY)     ? "parity " : "",
1067
                   (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
1068
                   (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
1069
                   (errors & SPWL_ERR_AHB)        ? "AHB " : "");
1070
            link_is_up = 0;
1071
        }
1072
 
1073
        if ((cond & SPWL_COND_TIMECODE) != 0) {
1074
            timecode = spwl_get_timecode(spwh);
1075
            printf("  %4u.%03u: got tick, timecode = %d\n",
1076
                   millis / 1000, millis % 1000, timecode);
1077
        }
1078
    }
1079
 
1080
    /* Restore console mode. */
1081
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
1082
 
1083
    printf("  done\n");
1084
}
1085
 
1086
 
1087
/* Receive/send menu. */
1088
void menu_recvsend(int send)
1089
{
1090
    int opt;
1091
    int queued, eventloop;
1092
    int npacket, packetsize, blocksize;
1093
 
1094
    do {
1095
 
1096
        printf("\n---- %s packets ----\n", send ? "Send" : "Receive");
1097
        show_status();
1098
        printf(" 1.  Copy API; blocking calls\n");
1099
        printf(" 2.  Copy API; event loop\n");
1100
        printf(" 3.  Queue API; blocking calls\n");
1101
        printf(" 4.  Queue API; event loop\n");
1102
        printf(" 0.  Back to main menu\n");
1103
 
1104
        opt = get_opt(4);
1105
        if (opt > 0 && opt <= 4) {
1106
 
1107
            queued    = (opt == 3 || opt == 4);
1108
            eventloop = (opt == 2 || opt == 4);
1109
 
1110
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
1111
 
1112
            if (send)
1113
                packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
1114
            else
1115
                packetsize = 0;
1116
 
1117
            blocksize = 0;
1118
            while (send || !queued) {
1119
                blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
1120
                if ((blocksize & 3) == 0 || !queued)
1121
                    break;
1122
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
1123
            }
1124
 
1125
            if (npacket > 0) {
1126
                if (send) {
1127
                    do_data_test(queued, eventloop,
1128
                                 0, 0,
1129
                                 npacket, packetsize, blocksize,
1130
                                 0);
1131
                } else {
1132
                    do_data_test(queued, eventloop,
1133
                                 npacket, blocksize,
1134
                                 0, 0, 0,
1135
                                 0);
1136
                }
1137
            }
1138
        }
1139
    } while (opt != 0);
1140
}
1141
 
1142
 
1143
/* Loopback test menu. */
1144
void menu_loopback(int verify)
1145
{
1146
    int opt;
1147
    int queued, eventloop;
1148
    int npacket, packetsize, blocksize;
1149
 
1150
    do {
1151
 
1152
        printf("\n---- Loopback test %s ----\n",
1153
               verify ? "with data compare" : "(no compare)");
1154
        show_status();
1155
        printf(" 1.  Copy API; blocking calls; multi-threaded\n");
1156
        printf(" 2.  Copy API; event loop\n");
1157
        printf(" 3.  Queue API; blocking calls; multi-threaded\n");
1158
        printf(" 4.  Queue API; event loop\n");
1159
        printf(" 5.  Automatic test\n");
1160
        printf(" 0.  Back to main menu\n");
1161
 
1162
        opt = get_opt(5);
1163
        if (opt > 0 && opt <= 4) {
1164
 
1165
            queued    = (opt == 3 || opt == 4);
1166
            eventloop = (opt == 2 || opt == 4);
1167
 
1168
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
1169
            packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
1170
            while (1) {
1171
                blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
1172
                if ((blocksize & 3) == 0 || !queued)
1173
                    break;
1174
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
1175
            }
1176
 
1177
            if (npacket > 0) {
1178
                do_data_test(queued, eventloop,
1179
                             npacket, blocksize,
1180
                             npacket, packetsize, blocksize,
1181
                             verify);
1182
            }
1183
 
1184
        } else if (opt == 5) {
1185
 
1186
            do_autotest(verify);
1187
 
1188
        }
1189
 
1190
    } while (opt != 0);
1191
}
1192
 
1193
 
1194
/* Passive loopback menu. */
1195
void menu_passiveloop(void)
1196
{
1197
    int opt;
1198
    int queued, blocksize = 0;
1199
 
1200
    printf("\n---- Passive loopback mode----\n");
1201
    show_status();
1202
    printf(" 1.  Copy API\n");
1203
    printf(" 2.  Queue API\n");
1204
    printf(" 0.  Back to main menu\n");
1205
 
1206
    opt = get_opt(2);
1207
    if (opt > 0 && opt <= 2) {
1208
 
1209
        queued = (opt == 2);
1210
 
1211
        while (!queued) {
1212
            blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
1213
            if ((blocksize & 3) == 0 || !queued)
1214
                break;
1215
            printf("INVALID: block size must be a multiple of 4 in queued mode\n");
1216
        }
1217
 
1218
        do_passive_loopback(queued, blocksize);
1219
    }
1220
}
1221
 
1222
 
1223
/* Main menu. */
1224
void menu_main(void)
1225
{
1226
    int opt;
1227
 
1228
    do {
1229
        printf("\n==== SpaceWire Light Test ====\n");
1230
        show_status();
1231
        printf(" 1.  Re-initialize driver\n");
1232
        printf(" 2.  Set link mode\n");
1233
        printf(" 3.  Set link speed\n");
1234
        printf(" 4.  Receive packets\n");
1235
        printf(" 5.  Send packets\n");
1236
        printf(" 6.  Loopback test (no compare)\n");
1237
        printf(" 7.  Loopback test with data compare\n");
1238
        printf(" 8.  Passive loopback\n");
1239
        printf(" 9.  Send time code\n");
1240
        printf("10.  Show time codes and link events\n");
1241
        printf(" 0.  Exit\n");
1242
 
1243
        opt = get_opt(10);
1244
        switch (opt) {
1245
            case 1: do_init_driver(); break;
1246
            case 2: do_set_link_mode(); break;
1247
            case 3: do_set_link_speed(); break;
1248
            case 4: menu_recvsend(0); break;
1249
            case 5: menu_recvsend(1); break;
1250
            case 6: menu_loopback(0); break;
1251
            case 7: menu_loopback(1); break;
1252
            case 8: menu_passiveloop(); break;
1253
            case 9: do_send_timecode(); break;
1254
            case 10: do_recv_timecode(); break;
1255
        }
1256
 
1257
    } while (opt != 0);
1258
}
1259
 
1260
 
1261
/* Main program. */
1262
void Init(rtems_task_argument arg)
1263
{
1264
    int i;
1265
 
1266
    printf("\nSpaceWire Light test program for RTEMS\n\n");
1267
 
1268
    /* Put stdin in raw mode. */
1269
    {
1270
        struct termios tcattr;
1271
        tcgetattr(STDIN_FILENO, &tcattr);
1272
        tcattr.c_iflag &= ~IGNCR;
1273
        tcattr.c_lflag &= ~(ICANON | ECHO);
1274
        tcattr.c_cc[VMIN] = 1;
1275
        tcattr.c_cc[VTIME] = 0;
1276
        tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
1277
    }
1278
 
1279
    /* Create TX data pool. */
1280
    for (i = 0; i < MAX_BLOCK_SIZE; i++) {
1281
        int v = ((i & 1) << 7) | ((i & 2) << 5) |
1282
                ((i & 4) << 3) | ((i & 8) << 1) |
1283
                ((i & 16) >> 1) | ((i & 32) >> 3) |
1284
                ((i & 64) >> 5) | ((i & 128) >> 7);
1285
        v += (i >> 8);
1286
        txpool[i] = v;
1287
    }
1288
    memcpy(txpool + MAX_BLOCK_SIZE, txpool, MAX_BLOCK_SIZE);
1289
 
1290
    /* Open SpaceWire core */
1291
    spw_index = 0;
1292
    open_driver();
1293
 
1294
    /* Main menu. */
1295
    menu_main();
1296
 
1297
    /* Clean up. */
1298
    spwl_close(spwh);
1299
 
1300
    printf("\nExit.\n");
1301
    rtems_shutdown_executive(0);
1302
}
1303
 
1304
/* vim: expandtab softtabstop=4
1305
*/
1306
/* end */

powered by: WebSVN 2.1.0

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