xref: /titanic_52/usr/src/boot/sys/boot/i386/common/cons.c (revision c4fddd735b9cdcc6c9ba9bf9fedeb58f1cc70b39)
1 /*-
2  * Copyright (c) 1998 Robert Nordier
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are freely
6  * permitted provided that the above copyright notice and this
7  * paragraph and the following disclaimer are duplicated in all
8  * such forms.
9  *
10  * This software is provided "AS IS" and without any express or
11  * implied warranties, including, without limitation, the implied
12  * warranties of merchantability and fitness for a particular
13  * purpose.
14  */
15 
16 #include <sys/cdefs.h>
17 
18 #include <sys/param.h>
19 
20 #include <machine/psl.h>
21 
22 #include <btxv86.h>
23 
24 #include "lib.h"
25 #include "rbx.h"
26 #include "util.h"
27 #include "cons.h"
28 
29 #define SECOND		18	/* Circa that many ticks in a second. */
30 
31 uint8_t ioctrl = IO_KEYBOARD;
32 
33 void
34 putc(int c)
35 {
36 
37 	v86.ctl = V86_FLAGS;
38 	v86.addr = 0x10;
39 	v86.eax = 0xe00 | (c & 0xff);
40 	v86.ebx = 0x7;
41 	v86int();
42 }
43 
44 void
45 xputc(int c)
46 {
47 
48 	if (ioctrl & IO_KEYBOARD)
49 		putc(c);
50 	if (ioctrl & IO_SERIAL)
51 		sio_putc(c);
52 }
53 
54 void
55 putchar(int c)
56 {
57 
58 	if (c == '\n')
59 		xputc('\r');
60 	xputc(c);
61 }
62 
63 int
64 getc(int fn)
65 {
66 
67 	v86.ctl = V86_FLAGS;
68 	v86.addr = 0x16;
69 	v86.eax = fn << 8;
70 	v86int();
71 
72 	if (fn == 0)
73 		return (v86.eax);
74 
75 	if (V86_ZR(v86.efl))
76 		return (0);
77 	return (v86.eax);
78 }
79 
80 int
81 xgetc(int fn)
82 {
83 
84 	if (OPT_CHECK(RBX_NOINTR))
85 		return (0);
86 	for (;;) {
87 		if (ioctrl & IO_KEYBOARD && getc(1))
88 			return (fn ? 1 : getc(0));
89 		if (ioctrl & IO_SERIAL && sio_ischar())
90 			return (fn ? 1 : sio_getc());
91 		if (fn)
92 			return (0);
93 	}
94 	/* NOTREACHED */
95 }
96 
97 int
98 keyhit(unsigned int secs)
99 {
100 	uint32_t t0, t1, c;
101 
102 	if (OPT_CHECK(RBX_NOINTR))
103 		return (0);
104 	secs *= SECOND;
105 	t0 = 0;
106 	for (;;) {
107 		/*
108 		 * The extra comparison is an attempt to work around
109 		 * what appears to be a bug in QEMU and Bochs. Both emulators
110 		 * sometimes report a key-press with scancode one and ascii zero
111 		 * when no such key is pressed in reality. As far as I can tell,
112 		 * this only happens shortly after a reboot.
113 		 */
114 		c = xgetc(1);
115 		if (c != 0 && c != 0x0100)
116 			return (1);
117 		if (secs > 0) {
118 			t1 = *(uint32_t *)PTOV(0x46c);
119 			if (!t0)
120 				t0 = t1;
121 			if (t1 < t0 || t1 >= t0 + secs)
122 				return (0);
123 		}
124 	}
125 	/* NOTREACHED */
126 }
127 
128 void
129 getstr(char *cmdstr, size_t cmdstrsize)
130 {
131 	char *s;
132 	int c;
133 
134 	s = cmdstr;
135 	for (;;) {
136 		c = xgetc(0);
137 
138 		/* Translate some extended codes. */
139 		switch (c) {
140 		case 0x5300:	/* delete */
141 			c = '\177';
142 			break;
143 		default:
144 			c &= 0xff;
145 			break;
146 		}
147 
148 		switch (c) {
149 		case '\177':
150 		case '\b':
151 			if (s > cmdstr) {
152 				s--;
153 				printf("\b \b");
154 			}
155 			break;
156 		case '\n':
157 		case '\r':
158 			*s = 0;
159 			return;
160 		default:
161 			if (c >= 0x20 && c <= 0x7e) {
162 				if (s - cmdstr < cmdstrsize - 1)
163 					*s++ = c;
164 				putchar(c);
165 			}
166 			break;
167 		}
168 	}
169 }
170 
171 int
172 getchar(void)
173 {
174 	return (xgetc(0) & 0xff);
175 }
176