/[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 6 - (show annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 18082 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


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.8 2005/05/29 17:51:45 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(50);
190 sprintf(a[7], "-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 struct console_handle *chp;
645
646 if (machine == NULL || consolename == NULL) {
647 printf("console_start_slave(): NULL ptr\n");
648 exit(1);
649 }
650
651 chp = console_new_handle(consolename, &handle);
652
653 chp->name = malloc(strlen(machine->name) + strlen(consolename) + 100);
654 if (chp->name == NULL) {
655 printf("out of memory\n");
656 exit(1);
657 }
658 sprintf(chp->name, "GXemul: '%s' %s", machine->name, consolename);
659
660 #if 0
661 if (!machine->use_x11) {
662 return handle;
663 }
664 #endif
665 chp->using_xterm = USING_XTERM_BUT_NOT_YET_OPEN;
666
667 return handle;
668 }
669
670
671 /*
672 * console_start_slave_inputonly():
673 *
674 * Similar to console_start_slave(), but doesn't open an xterm. This is
675 * useful for devices such as keyboard controllers, that need to have an
676 * input queue, but no xterm window associated with it.
677 *
678 * On success, an integer >= 0 is returned. This can then be used as a
679 * 'handle' when writing to or reading from an emulated console.
680 *
681 * On failure, -1 is returned.
682 */
683 int console_start_slave_inputonly(struct machine *machine, char *consolename)
684 {
685 struct console_handle *chp;
686 int handle;
687
688 if (machine == NULL || consolename == NULL) {
689 printf("console_start_slave(): NULL ptr\n");
690 exit(1);
691 }
692
693 chp = console_new_handle(consolename, &handle);
694 chp->inputonly = 1;
695
696 chp->name = malloc(strlen(machine->name) + strlen(consolename) + 100);
697 if (chp->name == NULL) {
698 printf("out of memory\n");
699 exit(1);
700 }
701 sprintf(chp->name, "GXemul: '%s' %s", machine->name, consolename);
702
703 return handle;
704 }
705
706
707 /*
708 * console_init_main():
709 *
710 * Put host's console into single-character (non-canonical) mode.
711 */
712 void console_init_main(struct emul *emul)
713 {
714 int i, tra;
715
716 if (console_initialized)
717 return;
718
719 tcgetattr(STDIN_FILENO, &console_oldtermios);
720 memcpy(&console_curtermios, &console_oldtermios,
721 sizeof (struct termios));
722
723 console_curtermios.c_lflag &= ~ICANON;
724 console_curtermios.c_cc[VTIME] = 0;
725 console_curtermios.c_cc[VMIN] = 1;
726
727 console_curtermios.c_lflag &= ~ECHO;
728
729 /*
730 * Most guest OSes seem to work ok without ~ICRNL, but Linux on
731 * DECstation requires it to be usable. Unfortunately, clearing
732 * out ICRNL makes tracing with '-t ... |more' akward, as you
733 * might need to use CTRL-J instead of the enter key. Hence,
734 * this bit is only cleared if we're not tracing:
735 */
736 tra = 0;
737 for (i=0; i<emul->n_machines; i++)
738 if (emul->machines[i]->show_trace_tree ||
739 emul->machines[i]->instruction_trace ||
740 emul->machines[i]->register_dump)
741 tra = 1;
742 if (!tra)
743 console_curtermios.c_iflag &= ~ICRNL;
744
745 tcsetattr(STDIN_FILENO, TCSANOW, &console_curtermios);
746
747 console_stdout_pending = 1;
748 console_handles[MAIN_CONSOLE].fifo_head = 0;
749 console_handles[MAIN_CONSOLE].fifo_tail = 0;
750
751 console_mouse_x = 0;
752 console_mouse_y = 0;
753 console_mouse_buttons = 0;
754
755 console_initialized = 1;
756 }
757
758
759 /*
760 * console_allow_slaves():
761 *
762 * This function tells the console subsystem whether or not to open up
763 * slave xterms for each emulated serial controller.
764 */
765 void console_allow_slaves(int allow)
766 {
767 allow_slaves = allow;
768 }
769
770
771 /*
772 * console_init():
773 *
774 * This function should be called before any other console_*() function
775 * is used.
776 */
777 void console_init(void)
778 {
779 int handle;
780 struct console_handle *chp;
781
782 chp = console_new_handle("MAIN", &handle);
783 if (handle != MAIN_CONSOLE) {
784 printf("console_init(): fatal error: could not create"
785 " console 0: handle = %i\n", handle);
786 exit(1);
787 }
788 }
789

  ViewVC Help
Powered by ViewVC 1.1.26