/[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

Annotation of /trunk/src/console.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide 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 dpavlin 2 /*
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 dpavlin 6 * $Id: console.c,v 1.8 2005/05/29 17:51:45 debug Exp $
29 dpavlin 2 *
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 dpavlin 6 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 dpavlin 2
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