/[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 10 - (hide annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 5 months 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 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 10 * $Id: console.c,v 1.9 2005/06/26 11:36:27 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 dpavlin 10 a[7] = malloc(80);
190     snprintf(a[7], 80, "-WW@S%i,%i", filedes[0], filedesB[1]);
191 dpavlin 6 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 dpavlin 10 size_t mlen;
645 dpavlin 2 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 dpavlin 10 mlen = strlen(machine->name) + strlen(consolename) + 40;
655     chp->name = malloc(mlen);
656 dpavlin 2 if (chp->name == NULL) {
657     printf("out of memory\n");
658     exit(1);
659     }
660 dpavlin 10 snprintf(chp->name, mlen, "GXemul: '%s' %s",
661     machine->name, consolename);
662 dpavlin 2
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 dpavlin 10 size_t mlen;
691 dpavlin 2
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 dpavlin 10 mlen = strlen(machine->name) + strlen(consolename) + 40;
701     chp->name = malloc(mlen);
702 dpavlin 2 if (chp->name == NULL) {
703     printf("out of memory\n");
704     exit(1);
705     }
706 dpavlin 10 snprintf(chp->name, mlen, "GXemul: '%s' %s",
707     machine->name, consolename);
708 dpavlin 2
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