]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/i386/common/cons.c
MFC r325834,r325997,326502: Move sys/boot to stand/
[FreeBSD/FreeBSD.git] / stand / i386 / common / cons.c
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 }