/[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 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 19157 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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 20 * $Id: console.c,v 1.10 2005/11/23 02:17:00 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 dpavlin 20 * console_are_slaves_allowed():
779     *
780     * Returns the value of allow_slaves.
781     */
782     int console_are_slaves_allowed(void)
783     {
784     return allow_slaves;
785     }
786    
787    
788     /*
789     * console_warn_if_slaves_are_needed():
790     *
791     * Prints a warning if slave xterms are needed (i.e. there is more than one
792     * console handle in use), but they are not currently allowed.
793     */
794     void console_warn_if_slaves_are_needed(void)
795     {
796     int i, n = 0;
797     for (i=MAIN_CONSOLE+1; i<n_console_handles; i++)
798     if (console_handles[i].in_use &&
799     !console_handles[i].using_xterm)
800     n ++;
801    
802     if (!allow_slaves && n > 1) {
803     fatal("#\n# WARNING! More than one console output is in use,"
804     "\n# but xterm slaves are not enabled. Behaviour will\n"
805     "# be undefined. (Use -x to enable slave xterms.)\n#\n");
806     for (i=MAIN_CONSOLE+1; i<n_console_handles; i++)
807     if (console_handles[i].in_use &&
808     !console_handles[i].using_xterm)
809     fatal("# console handle %i: '%s'\n",
810     i, console_handles[i].name);
811     fatal("#\n");
812     }
813     }
814    
815    
816     /*
817 dpavlin 2 * console_init():
818     *
819     * This function should be called before any other console_*() function
820     * is used.
821     */
822     void console_init(void)
823     {
824     int handle;
825     struct console_handle *chp;
826    
827     chp = console_new_handle("MAIN", &handle);
828     if (handle != MAIN_CONSOLE) {
829     printf("console_init(): fatal error: could not create"
830     " console 0: handle = %i\n", handle);
831     exit(1);
832     }
833     }
834    

  ViewVC Help
Powered by ViewVC 1.1.26