/[gxemul]/trunk/src/console.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/console.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Mon Oct 8 16:18:27 2007 UTC (12 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 18165 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


1 /*
2 * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: console.c,v 1.9 2005/06/26 11:36:27 debug Exp $
29 *
30 * Generic console support functions.
31 *
32 * This is used by individual device drivers, for example serial controllers,
33 * to attach stdin/stdout of the host system to a specific device.
34 *
35 * NOTE: This stuff is non-reentrant.
36 */
37
38 #include <errno.h>
39 #include <signal.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <termios.h>
44 #include <unistd.h>
45 #include <sys/types.h>
46
47 #include "console.h"
48 #include "emul.h"
49 #include "machine.h"
50 #include "memory.h"
51 #include "misc.h"
52
53
54 extern char *progname;
55
56
57 static struct termios console_oldtermios;
58 static struct termios console_curtermios;
59
60 /* For 'slave' mode: */
61 static struct termios console_slave_tios;
62 static int console_slave_outputd;
63
64 static int console_initialized = 0;
65 static int console_stdout_pending;
66
67 #define CONSOLE_FIFO_LEN 4096
68
69 /* Mouse coordinates: */
70 static int console_framebuffer_mouse_x; /* absolute x, 0-based */
71 static int console_framebuffer_mouse_y; /* absolute y, 0-based */
72 static int console_framebuffer_mouse_fb_nr; /* fb_number of last
73 framebuffer cursor update */
74
75 static int console_mouse_x; /* absolute x, 0-based */
76 static int console_mouse_y; /* absolute y, 0-based */
77 static int console_mouse_fb_nr; /* framebuffer number of
78 host movement, 0-based */
79 static int console_mouse_buttons; /* left=4, middle=2, right=1 */
80
81 static int allow_slaves = 0;
82
83 struct console_handle {
84 int in_use;
85 int using_xterm;
86 int inputonly;
87
88 char *name;
89
90 int w_descriptor;
91 int r_descriptor;
92
93 unsigned char fifo[CONSOLE_FIFO_LEN];
94 int fifo_head;
95 int fifo_tail;
96 };
97
98 #define NOT_USING_XTERM 0
99 #define USING_XTERM_BUT_NOT_YET_OPEN 1
100 #define USING_XTERM 2
101
102 /* A simple array of console_handles */
103 static struct console_handle *console_handles = NULL;
104 static int n_console_handles = 0;
105
106
107 /*
108 * console_deinit():
109 *
110 * Restore host's console settings.
111 */
112 void console_deinit(void)
113 {
114 if (!console_initialized)
115 return;
116
117 tcsetattr(STDIN_FILENO, TCSANOW, &console_oldtermios);
118
119 console_initialized = 0;
120 }
121
122
123 /*
124 * console_sigcont():
125 *
126 * If the user presses CTRL-Z (to stop the emulator process) and then
127 * continues, we have to make sure that the right termios settings are
128 * active. (This should be set as the SIGCONT signal handler in src/emul.c.)
129 */
130 void console_sigcont(int x)
131 {
132 if (!console_initialized)
133 return;
134
135 /* Make sure our 'current' termios setting is active: */
136 tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
137
138 /* Reset the signal handler: */
139 signal(SIGCONT, console_sigcont);
140 }
141
142
143 /*
144 * start_xterm():
145 *
146 * When using X11, this routine tries to start up an xterm, with another
147 * copy of gxemul inside. The other gxemul copy is given arguments
148 * that will cause it to run console_slave().
149 */
150 static void start_xterm(int handle)
151 {
152 int filedes[2];
153 int filedesB[2];
154 int res;
155 char **a;
156 pid_t p;
157
158 res = pipe(filedes);
159 if (res) {
160 printf("[ start_xterm(): pipe(): %i ]\n", errno);
161 exit(1);
162 }
163
164 res = pipe(filedesB);
165 if (res) {
166 printf("[ start_xterm(): pipe(): %i ]\n", errno);
167 exit(1);
168 }
169
170 /* printf("filedes = %i,%i\n", filedes[0], filedes[1]); */
171 /* printf("filedesB = %i,%i\n", filedesB[0], filedesB[1]); */
172
173 /* NOTE/warning: Hardcoded max nr of args! */
174 a = malloc(sizeof(char *) * 20);
175 if (a == NULL) {
176 fprintf(stderr, "console_start_slave(): out of memory\n");
177 exit(1);
178 }
179
180 a[0] = getenv("XTERM");
181 if (a[0] == NULL)
182 a[0] = "xterm";
183 a[1] = "-geometry";
184 a[2] = "80x25";
185 a[3] = "-title";
186 a[4] = console_handles[handle].name;
187 a[5] = "-e";
188 a[6] = progname;
189 a[7] = malloc(80);
190 snprintf(a[7], 80, "-WW@S%i,%i", filedes[0], filedesB[1]);
191 a[8] = NULL;
192
193 p = fork();
194 if (p == -1) {
195 printf("[ console_start_slave(): ERROR while trying to "
196 "fork(): %i ]\n", errno);
197 exit(1);
198 } else if (p == 0) {
199 close(filedes[1]);
200 close(filedesB[0]);
201
202 p = setsid();
203 if (p < 0)
204 printf("[ console_start_slave(): ERROR while trying "
205 "to do a setsid(): %i ]\n", errno);
206
207 res = execvp(a[0], a);
208 printf("[ console_start_slave(): ERROR while trying to "
209 "execvp(\"");
210 while (a[0] != NULL) {
211 printf("%s", a[0]);
212 if (a[1] != NULL)
213 printf(" ");
214 a++;
215 }
216 printf("\"): %i ]\n", errno);
217 exit(1);
218 }
219
220 /* TODO: free a and a[*] */
221
222 close(filedes[0]);
223 close(filedesB[1]);
224
225 console_handles[handle].using_xterm = USING_XTERM;
226
227 /*
228 * write to filedes[1], read from filedesB[0]
229 */
230
231 console_handles[handle].w_descriptor = filedes[1];
232 console_handles[handle].r_descriptor = filedesB[0];
233 }
234
235
236 /*
237 * d_avail():
238 *
239 * Returns 1 if anything is available on a descriptor.
240 */
241 static int d_avail(int d)
242 {
243 fd_set rfds;
244 struct timeval tv;
245
246 FD_ZERO(&rfds);
247 FD_SET(d, &rfds);
248 tv.tv_sec = 0;
249 tv.tv_usec = 0;
250 return select(d+1, &rfds, NULL, NULL, &tv);
251 }
252
253
254 /*
255 * console_makeavail():
256 *
257 * Put a character in the queue, so that it will be avaiable,
258 * by inserting it into the char fifo.
259 */
260 void console_makeavail(int handle, char ch)
261 {
262 console_handles[handle].fifo[
263 console_handles[handle].fifo_head] = ch;
264 console_handles[handle].fifo_head = (
265 console_handles[handle].fifo_head + 1) % CONSOLE_FIFO_LEN;
266
267 if (console_handles[handle].fifo_head ==
268 console_handles[handle].fifo_tail)
269 fatal("[ WARNING: console fifo overrun, handle %i ]\n", handle);
270 }
271
272
273 /*
274 * console_stdin_avail():
275 *
276 * Returns 1 if a char is available from a handle's read descriptor,
277 * 0 otherwise.
278 */
279 static int console_stdin_avail(int handle)
280 {
281 if (!allow_slaves)
282 return d_avail(STDIN_FILENO);
283
284 if (console_handles[handle].using_xterm ==
285 USING_XTERM_BUT_NOT_YET_OPEN)
286 return 0;
287
288 return d_avail(console_handles[handle].r_descriptor);
289 }
290
291
292 /*
293 * console_charavail():
294 *
295 * Returns 1 if a char is available in the fifo, 0 otherwise.
296 */
297 int console_charavail(int handle)
298 {
299 while (console_stdin_avail(handle)) {
300 unsigned char ch[100]; /* = getchar(); */
301 ssize_t len;
302 int i, d;
303
304 if (!allow_slaves)
305 d = STDIN_FILENO;
306 else
307 d = console_handles[handle].r_descriptor;
308
309 len = read(d, ch, sizeof(ch));
310
311 for (i=0; i<len; i++) {
312 /* printf("[ %i: %i ]\n", i, ch[i]); */
313
314 if (!allow_slaves) {
315 /* Ugly hack: convert ctrl-b into ctrl-c.
316 (TODO: fix) */
317 if (ch[i] == 2)
318 ch[i] = 3;
319 }
320
321 console_makeavail(handle, ch[i]);
322 }
323 }
324
325 if (console_handles[handle].fifo_head ==
326 console_handles[handle].fifo_tail)
327 return 0;
328
329 return 1;
330 }
331
332
333 /*
334 * console_readchar():
335 *
336 * Returns 0..255 if a char was available, -1 otherwise.
337 */
338 int console_readchar(int handle)
339 {
340 int ch;
341
342 if (!console_charavail(handle))
343 return -1;
344
345 ch = console_handles[handle].fifo[console_handles[handle].fifo_tail];
346 console_handles[handle].fifo_tail ++;
347 console_handles[handle].fifo_tail %= CONSOLE_FIFO_LEN;
348
349 return ch;
350 }
351
352
353 /*
354 * console_putchar():
355 *
356 * Prints a char to stdout, and sets the console_stdout_pending flag.
357 */
358 void console_putchar(int handle, int ch)
359 {
360 char buf[1];
361
362 if (!allow_slaves) {
363 /* stdout: */
364 putchar(ch);
365
366 /* Assume flushes by OS or libc on newlines: */
367 if (ch == '\n')
368 console_stdout_pending = 0;
369 else
370 console_stdout_pending = 1;
371
372 return;
373 }
374
375 if (!console_handles[handle].in_use) {
376 printf("[ console_putchar(): handle %i not in"
377 " use! ]\n", handle);
378 return;
379 }
380
381 if (console_handles[handle].using_xterm ==
382 USING_XTERM_BUT_NOT_YET_OPEN)
383 start_xterm(handle);
384
385 buf[0] = ch;
386 write(console_handles[handle].w_descriptor, buf, 1);
387 }
388
389
390 /*
391 * console_flush():
392 *
393 * Flushes stdout, if necessary, and resets console_stdout_pending to zero.
394 */
395 void console_flush(void)
396 {
397 if (console_stdout_pending)
398 fflush(stdout);
399
400 console_stdout_pending = 0;
401 }
402
403
404 /*
405 * console_mouse_coordinates():
406 *
407 * Sets mouse coordinates. Called by for example an X11 event handler.
408 * x and y are absolute coordinates, fb_nr is where the mouse movement
409 * took place.
410 */
411 void console_mouse_coordinates(int x, int y, int fb_nr)
412 {
413 /* TODO: fb_nr isn't used yet. */
414
415 console_mouse_x = x;
416 console_mouse_y = y;
417 console_mouse_fb_nr = fb_nr;
418 }
419
420
421 /*
422 * console_mouse_button():
423 *
424 * Sets a mouse button to be pressed or released. Called by for example an
425 * X11 event handler. button is 1 (left), 2 (middle), or 3 (right), and
426 * pressed = 1 for pressed, 0 for not pressed.
427 */
428 void console_mouse_button(int button, int pressed)
429 {
430 int mask = 1 << (3-button);
431
432 if (pressed)
433 console_mouse_buttons |= mask;
434 else
435 console_mouse_buttons &= ~mask;
436 }
437
438
439 /*
440 * console_get_framebuffer_mouse():
441 *
442 * TODO: Comment
443 */
444 void console_get_framebuffer_mouse(int *x, int *y, int *fb_nr)
445 {
446 *x = console_framebuffer_mouse_x;
447 *y = console_framebuffer_mouse_y;
448 *fb_nr = console_framebuffer_mouse_fb_nr;
449 }
450
451
452 /*
453 * console_set_framebuffer_mouse():
454 *
455 * A framebuffer device calls this function when it sets the
456 * position of a cursor (ie a mouse cursor).
457 */
458 void console_set_framebuffer_mouse(int x, int y, int fb_nr)
459 {
460 console_framebuffer_mouse_x = x;
461 console_framebuffer_mouse_y = y;
462 console_framebuffer_mouse_fb_nr = fb_nr;
463 }
464
465
466 /*
467 * console_getmouse():
468 *
469 * Puts current mouse data into the variables pointed to by
470 * the arguments.
471 */
472 void console_getmouse(int *x, int *y, int *buttons, int *fb_nr)
473 {
474 *x = console_mouse_x;
475 *y = console_mouse_y;
476 *buttons = console_mouse_buttons;
477 *fb_nr = console_mouse_fb_nr;
478 }
479
480
481 /*
482 * console_slave_sigint():
483 */
484 static void console_slave_sigint(int x)
485 {
486 char buf[1];
487
488 /* Send a ctrl-c: */
489 buf[0] = 3;
490 write(console_slave_outputd, buf, sizeof(buf));
491
492 /* Reset the signal handler: */
493 signal(SIGINT, console_slave_sigint);
494 }
495
496
497 /*
498 * console_slave_sigcont():
499 *
500 * See comment for console_sigcont. This is for used by console_slave().
501 */
502 static void console_slave_sigcont(int x)
503 {
504 /* Make sure our 'current' termios setting is active: */
505 tcsetattr(STDIN_FILENO, TCSANOW, &console_slave_tios);
506
507 /* Reset the signal handler: */
508 signal(SIGCONT, console_slave_sigcont);
509 }
510
511
512 /*
513 * console_slave():
514 *
515 * This function is used when running with X11, and gxemul opens up
516 * separate xterms for each emulated terminal or serial port.
517 */
518 void console_slave(char *arg)
519 {
520 int inputd;
521 int len;
522 char *p;
523 char buf[400];
524
525 /* arg = '3,6' or similar, input and output descriptors */
526 /* printf("console_slave(): arg = '%s'\n", arg); */
527
528 inputd = atoi(arg);
529 p = strchr(arg, ',');
530 if (p == NULL) {
531 printf("console_slave(): bad arg '%s'\n", arg);
532 sleep(5);
533 exit(1);
534 }
535 console_slave_outputd = atoi(p+1);
536
537 /* Set the terminal to raw mode: */
538 tcgetattr(STDIN_FILENO, &console_slave_tios);
539
540 console_slave_tios.c_lflag &= ~ICANON;
541 console_slave_tios.c_cc[VTIME] = 0;
542 console_slave_tios.c_cc[VMIN] = 1;
543 console_slave_tios.c_lflag &= ~ECHO;
544 console_slave_tios.c_iflag &= ~ICRNL;
545 tcsetattr(STDIN_FILENO, TCSANOW, &console_slave_tios);
546
547 signal(SIGINT, console_slave_sigint);
548 signal(SIGCONT, console_slave_sigcont);
549
550 for (;;) {
551 /* TODO: select() on both inputd and stdin */
552
553 if (d_avail(inputd)) {
554 len = read(inputd, buf, sizeof(buf) - 1);
555 if (len < 1)
556 exit(0);
557 buf[len] = '\0';
558 printf("%s", buf);
559 fflush(stdout);
560 }
561
562 if (d_avail(STDIN_FILENO)) {
563 len = read(STDIN_FILENO, buf, sizeof(buf));
564 if (len < 1)
565 exit(0);
566 write(console_slave_outputd, buf, len);
567 }
568
569 usleep(100);
570 }
571 }
572
573
574 /*
575 * console_new_handle():
576 *
577 * Allocates a new console_handle struct, and returns a pointer to it.
578 *
579 * For internal use.
580 */
581 static struct console_handle *console_new_handle(char *name, int *handlep)
582 {
583 struct console_handle *chp;
584 int i, n, found_free = -1;
585
586 /* Reuse an old slot, if possible: */
587 n = n_console_handles;
588 for (i=0; i<n; i++)
589 if (!console_handles[i].in_use) {
590 found_free = i;
591 break;
592 }
593
594 if (found_free == -1) {
595 /* Let's realloc console_handles[], to make room
596 for the new one: */
597 console_handles = realloc(console_handles, sizeof(
598 struct console_handle) * (n_console_handles + 1));
599 if (console_handles == NULL) {
600 printf("console_new_handle(): out of memory\n");
601 exit(1);
602 }
603 found_free = n_console_handles;
604 n_console_handles ++;
605 }
606
607 chp = &console_handles[found_free];
608 memset(chp, 0, sizeof(struct console_handle));
609
610 chp->in_use = 1;
611 chp->name = strdup(name);
612 if (chp->name == NULL) {
613 printf("console_new_handle(): out of memory\n");
614 exit(1);
615 }
616
617 *handlep = found_free;
618 return chp;
619 }
620
621
622 /*
623 * console_start_slave():
624 *
625 * When using X11:
626 *
627 * This routine tries to start up an xterm, with another copy of gxemul
628 * inside. The other gxemul copy is given arguments that will cause it
629 * to run console_slave().
630 *
631 * When not using X11: Things will seem to work the same way without X11,
632 * but no xterm will actually be started.
633 *
634 * consolename should be something like "serial 0".
635 *
636 * On success, an integer >= 0 is returned. This can then be used as a
637 * 'handle' when writing to or reading from an emulated console.
638 *
639 * On failure, -1 is returned.
640 */
641 int console_start_slave(struct machine *machine, char *consolename)
642 {
643 int handle;
644 size_t mlen;
645 struct console_handle *chp;
646
647 if (machine == NULL || consolename == NULL) {
648 printf("console_start_slave(): NULL ptr\n");
649 exit(1);
650 }
651
652 chp = console_new_handle(consolename, &handle);
653
654 mlen = strlen(machine->name) + strlen(consolename) + 40;
655 chp->name = malloc(mlen);
656 if (chp->name == NULL) {
657 printf("out of memory\n");
658 exit(1);
659 }
660 snprintf(chp->name, mlen, "GXemul: '%s' %s",
661 machine->name, consolename);
662
663 #if 0
664 if (!machine->use_x11) {
665 return handle;
666 }
667 #endif
668 chp->using_xterm = USING_XTERM_BUT_NOT_YET_OPEN;
669
670 return handle;
671 }
672
673
674 /*
675 * console_start_slave_inputonly():
676 *
677 * Similar to console_start_slave(), but doesn't open an xterm. This is
678 * useful for devices such as keyboard controllers, that need to have an
679 * input queue, but no xterm window associated with it.
680 *
681 * On success, an integer >= 0 is returned. This can then be used as a
682 * 'handle' when writing to or reading from an emulated console.
683 *
684 * On failure, -1 is returned.
685 */
686 int console_start_slave_inputonly(struct machine *machine, char *consolename)
687 {
688 struct console_handle *chp;
689 int handle;
690 size_t mlen;
691
692 if (machine == NULL || consolename == NULL) {
693 printf("console_start_slave(): NULL ptr\n");
694 exit(1);
695 }
696
697 chp = console_new_handle(consolename, &handle);
698 chp->inputonly = 1;
699
700 mlen = strlen(machine->name) + strlen(consolename) + 40;
701 chp->name = malloc(mlen);
702 if (chp->name == NULL) {
703 printf("out of memory\n");
704 exit(1);
705 }
706 snprintf(chp->name, mlen, "GXemul: '%s' %s",
707 machine->name, consolename);
708
709 return handle;
710 }
711
712
713 /*
714 * console_init_main():
715 *
716 * Put host's console into single-character (non-canonical) mode.
717 */
718 void console_init_main(struct emul *emul)
719 {
720 int i, tra;
721
722 if (console_initialized)
723 return;
724
725 tcgetattr(STDIN_FILENO, &console_oldtermios);
726 memcpy(&console_curtermios, &console_oldtermios,
727 sizeof (struct termios));
728
729 console_curtermios.c_lflag &= ~ICANON;
730 console_curtermios.c_cc[VTIME] = 0;
731 console_curtermios.c_cc[VMIN] = 1;
732
733 console_curtermios.c_lflag &= ~ECHO;
734
735 /*
736 * Most guest OSes seem to work ok without ~ICRNL, but Linux on
737 * DECstation requires it to be usable. Unfortunately, clearing
738 * out ICRNL makes tracing with '-t ... |more' akward, as you
739 * might need to use CTRL-J instead of the enter key. Hence,
740 * this bit is only cleared if we're not tracing:
741 */
742 tra = 0;
743 for (i=0; i<emul->n_machines; i++)
744 if (emul->machines[i]->show_trace_tree ||
745 emul->machines[i]->instruction_trace ||
746 emul->machines[i]->register_dump)
747 tra = 1;
748 if (!tra)
749 console_curtermios.c_iflag &= ~ICRNL;
750
751 tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
752
753 console_stdout_pending = 1;
754 console_handles[MAIN_CONSOLE].fifo_head = 0;
755 console_handles[MAIN_CONSOLE].fifo_tail = 0;
756
757 console_mouse_x = 0;
758 console_mouse_y = 0;
759 console_mouse_buttons = 0;
760
761 console_initialized = 1;
762 }
763
764
765 /*
766 * console_allow_slaves():
767 *
768 * This function tells the console subsystem whether or not to open up
769 * slave xterms for each emulated serial controller.
770 */
771 void console_allow_slaves(int allow)
772 {
773 allow_slaves = allow;
774 }
775
776
777 /*
778 * console_init():
779 *
780 * This function should be called before any other console_*() function
781 * is used.
782 */
783 void console_init(void)
784 {
785 int handle;
786 struct console_handle *chp;
787
788 chp = console_new_handle("MAIN", &handle);
789 if (handle != MAIN_CONSOLE) {
790 printf("console_init(): fatal error: could not create"
791 " console 0: handle = %i\n", handle);
792 exit(1);
793 }
794 }
795

  ViewVC Help
Powered by ViewVC 1.1.26