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