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