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