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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [redboot/] [v2_0/] [src/] [io.c] - Blame information for rev 1773

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      io.c
4
//
5
//      RedBoot I/O support
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
// Copyright (C) 2002 Gary Thomas
13
//
14
// eCos is free software; you can redistribute it and/or modify it under
15
// the terms of the GNU General Public License as published by the Free
16
// Software Foundation; either version 2 or (at your option) any later version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
// for more details.
22
//
23
// You should have received a copy of the GNU General Public License along
24
// with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26
//
27
// As a special exception, if other files instantiate templates or use macros
28
// or inline functions from this file, or you compile this file and link it
29
// with other works to produce a work based on this file, this file does not
30
// by itself cause the resulting work to be covered by the GNU General Public
31
// License. However the source code for this file must still be made available
32
// in accordance with section (3) of the GNU General Public License.
33
//
34
// This exception does not invalidate any other reasons why a work based on
35
// this file might be covered by the GNU General Public License.
36
//
37
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38
// at http://sources.redhat.com/ecos/ecos-license/
39
// -------------------------------------------
40
//####ECOSGPLCOPYRIGHTEND####
41
//==========================================================================
42
//#####DESCRIPTIONBEGIN####
43
//
44
// Author(s):    gthomas
45
// Contributors: gthomas,hmt,jlarmour
46
// Date:         2000-07-14
47
// Purpose:      
48
// Description:  
49
//              
50
// This code is part of RedBoot (tm).
51
//
52
//####DESCRIPTIONEND####
53
//
54
//==========================================================================
55
 
56
#include "redboot.h"
57
 
58
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
59
// GDB interface functions
60
extern void ungetDebugChar(char c);
61
#endif
62
 
63
static void
64
do_channel(int argc, char *argv[]);
65
 
66
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
67
RedBoot_cmd("channel",
68
            "Display/switch console channel",
69
            "[-1|<channel number>]",
70
            do_channel
71
    );
72
#else
73
RedBoot_cmd("channel",
74
            "Display/switch console channel",
75
            "[<channel number>]",
76
            do_channel
77
    );
78
#endif
79
 
80
static void
81
do_channel(int argc, char *argv[])
82
{
83
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
84
 
85
    if (argc == 2) {
86
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
87
        if (strcmp( argv[1], "-1") == 0) {
88
            console_selected = false;
89
            console_echo = true;
90
        } else
91
#endif
92
        {
93
            unsigned long chan;
94
            if ( !parse_num( argv[1], &chan, NULL, NULL) ) {
95
                diag_printf("** Error: invalid channel '%s'\n", argv[1]);
96
            } else {
97
                if (chan < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
98
                    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);
99
                    CYGACC_CALL_IF_SET_DEBUG_COMM(chan);
100
                    if (chan != cur)
101
                        console_echo = true;
102
                }
103
                else {
104
                    diag_printf("**Error: bad channel number '%s'\n", argv[1]);
105
                }
106
            }
107
        }
108
    }
109
    /* else display */
110
    else {
111
        diag_printf("Current console channel id: ");
112
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
113
        if (!console_selected)
114
            diag_printf("-1\n");
115
        else
116
#endif
117
            diag_printf("%d\n", cur);
118
    }
119
}
120
 
121
void
122
mon_write_char(char c)
123
{
124
    hal_virtual_comm_table_t *__chan;
125
 
126
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
127
    if (!console_selected) {
128
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
129
        int i;
130
        // Send output to all channels
131
        for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++) {
132
            CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
133
            __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
134
            CYGACC_COMM_IF_PUTC(*__chan, c);
135
        }
136
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
137
    } else
138
#endif
139
    {
140
        __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
141
        if (__chan)
142
            CYGACC_COMM_IF_PUTC(*__chan, c);
143
        else {
144
            __chan = CYGACC_CALL_IF_DEBUG_PROCS();
145
            CYGACC_COMM_IF_PUTC(*__chan, c);
146
        }
147
    }
148
}
149
 
150
static void
151
mon_read_char(char *c)
152
{
153
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
154
 
155
    if (__chan)
156
        *c = CYGACC_COMM_IF_GETC(*__chan);
157
    else {
158
        __chan = CYGACC_CALL_IF_DEBUG_PROCS();
159
        *c = CYGACC_COMM_IF_GETC(*__chan);
160
    }
161
}
162
 
163
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
164
static int _mon_timeout;
165
#endif
166
 
167
static bool
168
mon_read_char_with_timeout(char *c)
169
{
170
    bool res = false;
171
    hal_virtual_comm_table_t *__chan;
172
 
173
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
174
    if (!console_selected) {
175
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
176
        int i, j, tot;
177
        // Try input from all channels
178
        tot = 0;
179
        while (tot < _mon_timeout) {
180
            for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++, tot++) {
181
                CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
182
                __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
183
                res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c);
184
                if (res) {
185
                    // Input available on this channel, make it be the console
186
                    if (*c != '\0') {
187
                        // Don't chose this unless real data have arrived
188
                        console_selected = true;
189
                        CYGACC_CALL_IF_SET_DEBUG_COMM(i);
190
                        // Disable interrupts on all channels but this one
191
                        for (j = 0;  j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  j++) {
192
                            if (i != j) {
193
                                CYGACC_CALL_IF_SET_CONSOLE_COMM(j);
194
                                __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
195
                                CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
196
                            }
197
                        }
198
                        CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
199
                        return res;
200
                    }
201
                }
202
            }
203
        }
204
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
205
    } else
206
#endif
207
    {
208
        __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
209
        if (__chan)
210
            res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c);
211
        else {
212
            __chan = CYGACC_CALL_IF_DEBUG_PROCS();
213
            res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c);
214
        }
215
    }
216
    return res;
217
}
218
 
219
static void
220
mon_set_read_char_timeout(int ms)
221
{
222
    hal_virtual_comm_table_t *__chan;
223
 
224
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
225
    if (!console_selected) {
226
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
227
        int i;
228
        // Set timeout to minimum on each channel; total amounts to desired value
229
        _mon_timeout = ms;
230
        ms = 1;
231
        for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++) {
232
            CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
233
            if ((__chan = CYGACC_CALL_IF_CONSOLE_PROCS()) != 0) {
234
                CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms);
235
            }
236
        }
237
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
238
    } else
239
#endif
240
    {
241
        if ((__chan = CYGACC_CALL_IF_CONSOLE_PROCS()) != 0) {
242
            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms);
243
        }
244
        if ((__chan = CYGACC_CALL_IF_DEBUG_PROCS()) != 0) {
245
            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms);
246
        }
247
    }
248
}
249
 
250
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
251
#define __STRINGIFY(x) #x
252
#define _STRINGIFY(x) __STRINGIFY(x)
253
#define _STARTUP_STR _STRINGIFY(CYG_HAL_STARTUP) "}"
254
 
255
//
256
// Read a character from script.
257
// Return true if script character found, false if not.
258
//
259
static int
260
getc_script(char *cp)
261
{
262
    static bool newline = true;
263
    bool skip;
264
 
265
    while (script && *script) {
266
        if (newline && *script == '{') {
267
            skip = false;
268
            ++script;
269
 
270
            // skip if it isn't for this startup type
271
            if (strncmp(script, _STARTUP_STR, strlen(_STARTUP_STR)))
272
                skip = true;
273
 
274
            // skip past "{...}"
275
            while (*script && *script++ != '}')
276
                ;
277
 
278
            // skip script line if neccessary
279
            if (skip) {
280
                while (*script && *script++ != '\n')
281
                    ;
282
            } else
283
                newline = false;
284
 
285
        } else {
286
            *cp = *script++;
287
            if (*cp == '\n') {
288
              newline = true;
289
            } else {
290
              newline = false;
291
            }
292
            return true;
293
        }
294
    }
295
    return false;
296
}
297
#endif
298
 
299
//
300
// Read a line of input from the user
301
// Return:
302
//        _GETS_OK: 'n' valid characters received
303
//       _GETS_GDB: '$' (GDB lead-in)
304
//   _GETS_TIMEOUT: No input before timeout
305
//     _GETS_CTRLC: ^C typed
306
//
307
int
308
_rb_gets_preloaded(char *buf, int buflen, int timeout)
309
{
310
    char *ip = buf;   // Insertion point
311
    char *eol = buf;  // End of line
312
    char c;
313
    bool res = false;
314
    static char last_ch = '\0';
315
    int _timeout;
316
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
317
//
318
// Command line history support
319
//    ^P - Select previous line from history
320
//    ^N - Select next line from history
321
//    ^A - Move insertion [cursor] to start of line
322
//    ^E - Move cursor to end of line
323
//    ^B - Move cursor back [previous character]
324
//    ^F - Move cursor forward [next character]
325
//
326
#define _CL_NUM_LINES CYGNUM_REDBOOT_CMD_LINE_EDITING       // Number of lines to keep
327
    static char _cl_lines[_CL_NUM_LINES][CYGPKG_REDBOOT_MAX_CMD_LINE];
328
    static int  _cl_index = -1;      // Last known command line
329
    static int  _cl_max_index = -1;  // Last command in buffers
330
    int _index = _cl_index;  // Last saved line
331
    char *xp;
332
#endif
333
 
334
    // Display current buffer data
335
    while (*eol) {
336
        mon_write_char(*eol++);
337
    }
338
    ip = eol;
339
 
340
    while (true) {
341
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
342
        if (getc_script(&c))
343
            do_idle(false);
344
        else
345
#endif
346
        if ((timeout > 0) && (eol == buf)) {
347
#define MIN_TIMEOUT 50
348
            _timeout = timeout > MIN_TIMEOUT ? MIN_TIMEOUT : timeout;
349
            mon_set_read_char_timeout(_timeout);
350
            while (timeout > 0) {
351
                res = mon_read_char_with_timeout(&c);
352
                if (res) {
353
                    // Got a character
354
                    do_idle(false);
355
                    break;
356
                }
357
                timeout -= _timeout;
358
            }
359
            if (res == false) {
360
                do_idle(true);
361
                return _GETS_TIMEOUT;  // Input timed out
362
            }
363
        } else {
364
            mon_read_char(&c);
365
        }
366
        *eol = '\0';
367
        switch (c) {
368
#define CTRL(c) ((c)&0x1F)
369
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
370
        case CTRL('P'):
371
            // Fetch the previous line into the buffer
372
            if (_index >= 0) {
373
                // Erase the previous line [crude]
374
                while (ip != buf) {
375
                    mon_write_char('\b');
376
                    mon_write_char(' ');
377
                    mon_write_char('\b');
378
                    ip--;
379
                }
380
                strcpy(buf, _cl_lines[_index]);
381
                while (*ip) {
382
                    mon_write_char(*ip++);
383
                }
384
                eol = ip;
385
                // Move to previous line
386
                _index--;
387
                if (_index < 0) {
388
                    _index = _cl_max_index;
389
                }
390
            } else {
391
                mon_write_char(0x07);  // Audible bell on most devices
392
            }
393
            break;
394
        case CTRL('N'):
395
            // Fetch the next line into the buffer
396
            if (_index >= 0) {
397
                if (++_index > _cl_max_index) _index = 0;
398
                // Erase the previous line [crude]
399
                while (ip != buf) {
400
                    mon_write_char('\b');
401
                    mon_write_char(' ');
402
                    mon_write_char('\b');
403
                    ip--;
404
                }
405
                strcpy(buf, _cl_lines[_index]);
406
                while (*ip) {
407
                    mon_write_char(*ip++);
408
                }
409
                eol = ip;
410
            } else {
411
                mon_write_char(0x07);  // Audible bell on most devices
412
            }
413
            break;
414
        case CTRL('B'):
415
            // Move insertion point backwards
416
            if (ip != buf) {
417
                mon_write_char('\b');
418
                ip--;
419
            }
420
            break;
421
        case CTRL('F'):
422
            // Move insertion point forwards
423
            if (ip != eol) {
424
                mon_write_char(*ip++);
425
            }
426
            break;
427
        case CTRL('E'):
428
            // Move insertion point to end of line
429
            while (ip != eol) {
430
                mon_write_char(*ip++);
431
            }
432
            break;
433
        case CTRL('A'):
434
            // Move insertion point to beginning of line
435
            if (ip != buf) {
436
                xp = eol;
437
                while (xp-- != buf) {
438
                    mon_write_char('\b');
439
                }
440
            }
441
            ip = buf;
442
            break;
443
        case CTRL('K'):
444
            // Kill to the end of line
445
            if (ip != eol) {
446
                xp = ip;
447
                while (xp++ != eol) {
448
                    mon_write_char(' ');
449
                }
450
                while (--xp != ip) {
451
                    mon_write_char('\b');
452
                }
453
                eol = ip;
454
            }
455
            break;
456
        case CTRL('D'):
457
            // Erase the character under the cursor
458
            if (ip != eol) {
459
                xp = ip;
460
                eol--;
461
                while (xp != eol) {
462
                    *xp = *(xp+1);
463
                    mon_write_char(*xp++);
464
                }
465
                mon_write_char(' ');  // Erases last character
466
                mon_write_char('\b');
467
                while (xp-- != ip) {
468
                    mon_write_char('\b');
469
                }
470
            }
471
            break;
472
#endif // CYGNUM_REDBOOT_CMD_LINE_EDITING
473
        case CTRL('C'): // ^C
474
            // Abort current input
475
            diag_printf("^C\n");
476
            *buf = '\0';  // Nothing useful in buffer
477
            return _GETS_CTRLC;
478
        case '\n':
479
        case '\r':
480
            // If previous character was the "other" end-of-line, ignore this one
481
            if (((c == '\n') && (last_ch == '\r')) ||
482
                ((c == '\r') && (last_ch == '\n'))) {
483
                c = '\0';
484
                break;
485
            }
486
            // End of line
487
            if (console_echo) {
488
                mon_write_char('\r');
489
                mon_write_char('\n');
490
            }
491
            last_ch = c;
492
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
493
            if (cmd_history && (buf != eol)) {
494
                // Save current line - only when enabled
495
                if (++_cl_index == _CL_NUM_LINES) _cl_index = 0;
496
                if (_cl_index > _cl_max_index) _cl_max_index = _cl_index;
497
                strcpy(_cl_lines[_cl_index], buf);
498
            }
499
#endif
500
            return _GETS_OK;
501
        case '\b':
502
        case 0x7F:  // DEL
503
            if (ip != buf) {
504
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
505
                if (ip != eol) {
506
                    ip--;
507
                    mon_write_char('\b');
508
                    xp = ip;
509
                    while (xp != (eol-1)) {
510
                        *xp = *(xp+1);
511
                        mon_write_char(*xp++);
512
                    }
513
                    mon_write_char(' ');  // Erases last character
514
                    mon_write_char('\b');
515
                    while (xp-- != ip) {
516
                        mon_write_char('\b');
517
                    }
518
                } else {
519
                    if (console_echo) {
520
                        mon_write_char('\b');
521
                        mon_write_char(' ');
522
                        mon_write_char('\b');
523
                    }
524
                    ip--;
525
                }
526
                eol--;
527
#else
528
                if (console_echo) {
529
                    mon_write_char('\b');
530
                    mon_write_char(' ');
531
                    mon_write_char('\b');
532
                }
533
                ip--;
534
                eol--;
535
#endif
536
            }
537
            break;
538
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
539
        case '+': // fall through
540
        case '$':
541
            if (ip == buf || last_ch != '\\')
542
            {
543
                // Give up and try GDB protocol
544
                ungetDebugChar(c);  // Push back character so stubs will see it
545
                return _GETS_GDB;
546
            }
547
            if (last_ch == '\\') {
548
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
549
                if (ip == eol) {
550
                    // Just save \$ as $
551
                    eol = --ip;
552
                } else {
553
                    mon_write_char('\b');
554
                    *--ip = c;
555
                    mon_write_char(c);
556
                    break;
557
                }
558
#else
559
                ip--;  // Save \$ as $
560
#endif
561
            }
562
            // else fall through
563
#endif
564
        default:
565
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
566
            // If the insertion point is not at the end of line, make space for it
567
            if (ip != eol) {
568
                xp = eol;
569
                *++eol = '\0';
570
                while (xp != ip) {
571
                    *xp = *(xp-1);
572
                    xp--;
573
                }
574
            }
575
#endif
576
            if (console_echo) {
577
                mon_write_char(c);
578
            }
579
            if (ip == eol) {
580
                // Advance both pointers
581
                *ip++ = c;
582
                eol = ip;
583
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
584
            } else {
585
                // Just insert the character
586
                *ip++ = c;
587
                xp = ip;
588
                while (xp != eol) {
589
                    mon_write_char(*xp++);
590
                }
591
                while (xp-- != ip) {
592
                    mon_write_char('\b');
593
                }
594
#endif
595
            }
596
        }
597
        last_ch = c;
598
        if (ip == buf + buflen - 1) { // Buffer full
599
            *ip = '\0';
600
            return buflen;
601
        }
602
    }
603
}
604
 
605
int
606
_rb_gets(char *buf, int buflen, int timeout)
607
{
608
    *buf = '\0';  // Empty buffer
609
    return _rb_gets_preloaded(buf, buflen, timeout);
610
}
611
 
612
static bool
613
_verify_action(int timeout, char *fmt, va_list ap)
614
{
615
    char ans[8];
616
    int ret;
617
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
618
    // Don't ask if we're executing a script
619
    if (script && *script)
620
        return 1;
621
#endif
622
 
623
    diag_vprintf(fmt, ap);
624
    diag_printf(" - continue (y/n)? ");
625
    if ((ret = _rb_gets(ans, sizeof(ans), timeout)) > 0) {
626
        return ((ans[0] == 'y') || (ans[0] == 'Y'));
627
    } else {
628
        if (ret == _GETS_TIMEOUT) {
629
            diag_printf(" ** Timed out!\n");
630
        }
631
        return 0;  // Timed out or ^C
632
    }
633
}
634
 
635
bool
636
verify_action(char *fmt, ...)
637
{
638
    va_list ap;
639
 
640
    va_start(ap, fmt);
641
    return _verify_action(0, fmt, ap);
642
}
643
 
644
bool
645
verify_action_with_timeout(int timeout, char *fmt, ...)
646
{
647
    va_list ap;
648
 
649
    va_start(ap, fmt);
650
    return _verify_action(timeout, fmt, ap);
651
}

powered by: WebSVN 2.1.0

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