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