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