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
putc(int c)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
xputc(int c)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 static void
getcursor(int * row,int * col)55 getcursor(int *row, int *col)
56 {
57 v86.ctl = V86_FLAGS;
58 v86.addr = 0x10;
59 v86.eax = 0x300;
60 v86.ebx = 0x7;
61 v86int();
62
63 if (row != NULL)
64 *row = v86.edx >> 8;
65 if (col != NULL)
66 *col = v86.edx & 0xff;
67 }
68
69 void
putchar(int c)70 putchar(int c)
71 {
72 int i, col;
73
74 switch (c) {
75 case '\n':
76 xputc('\r');
77 break;
78 case '\t':
79 col = 0;
80 getcursor(NULL, &col);
81 col = 8 - (col % 8);
82 for (i = 0; i < col; i++)
83 xputc(' ');
84 return;
85 }
86 xputc(c);
87 }
88
89 int
getc(int fn)90 getc(int fn)
91 {
92
93 v86.ctl = V86_FLAGS;
94 v86.addr = 0x16;
95 v86.eax = fn << 8;
96 v86int();
97
98 if (fn == 0)
99 return (v86.eax);
100
101 if (V86_ZR(v86.efl))
102 return (0);
103 return (v86.eax);
104 }
105
106 int
xgetc(int fn)107 xgetc(int fn)
108 {
109
110 if (OPT_CHECK(RBX_NOINTR))
111 return (0);
112 for (;;) {
113 if (ioctrl & IO_KEYBOARD && getc(1))
114 return (fn ? 1 : getc(0));
115 if (ioctrl & IO_SERIAL && sio_ischar())
116 return (fn ? 1 : sio_getc());
117 if (fn)
118 return (0);
119 }
120 /* NOTREACHED */
121 }
122
123 int
keyhit(unsigned int secs)124 keyhit(unsigned int secs)
125 {
126 uint32_t t0, t1, c;
127
128 if (OPT_CHECK(RBX_NOINTR))
129 return (0);
130 secs *= SECOND;
131 t0 = 0;
132 for (;;) {
133 /*
134 * The extra comparison is an attempt to work around
135 * what appears to be a bug in QEMU and Bochs. Both emulators
136 * sometimes report a key-press with scancode one and ascii zero
137 * when no such key is pressed in reality. As far as I can tell,
138 * this only happens shortly after a reboot.
139 */
140 c = xgetc(1);
141 if (c != 0 && c != 0x0100)
142 return (1);
143 if (secs > 0) {
144 t1 = *(uint32_t *)PTOV(0x46c);
145 if (!t0)
146 t0 = t1;
147 if (t1 < t0 || t1 >= t0 + secs)
148 return (0);
149 }
150 }
151 /* NOTREACHED */
152 }
153
154 void
getstr(char * cmdstr,size_t cmdstrsize)155 getstr(char *cmdstr, size_t cmdstrsize)
156 {
157 char *s;
158 int c;
159
160 s = cmdstr;
161 for (;;) {
162 c = xgetc(0);
163
164 /* Translate some extended codes. */
165 switch (c) {
166 case 0x5300: /* delete */
167 c = '\177';
168 break;
169 default:
170 c &= 0xff;
171 break;
172 }
173
174 switch (c) {
175 case '\177':
176 case '\b':
177 if (s > cmdstr) {
178 s--;
179 printf("\b \b");
180 }
181 break;
182 case '\n':
183 case '\r':
184 *s = 0;
185 return;
186 default:
187 if (c >= 0x20 && c <= 0x7e) {
188 if (s - cmdstr < cmdstrsize - 1)
189 *s++ = c;
190 putchar(c);
191 }
192 break;
193 }
194 }
195 }
196
197 int
getchar(void)198 getchar(void)
199 {
200 return (xgetc(0) & 0xff);
201 }
202