cons.c revision 329175
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: stable/11/stand/i386/common/cons.c 329175 2018-02-12 17:44:35Z kevans $");
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
33uint8_t ioctrl = IO_KEYBOARD;
34
35void
36putc(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
46void
47xputc(int c)
48{
49
50	if (ioctrl & IO_KEYBOARD)
51		putc(c);
52	if (ioctrl & IO_SERIAL)
53		sio_putc(c);
54}
55
56void
57putchar(int c)
58{
59
60	if (c == '\n')
61		xputc('\r');
62	xputc(c);
63}
64
65int
66getc(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
82int
83xgetc(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
99int
100getchar(void)
101{
102
103	return (xgetc(0));
104}
105
106int
107keyhit(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
137void
138getstr(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}
179