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: releng/11.0/sys/boot/i386/common/cons.c 296963 2016-03-16 23:12:19Z allanjude $");
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
32uint8_t ioctrl = IO_KEYBOARD;
33
34void
35putc(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
45void
46xputc(int c)
47{
48
49	if (ioctrl & IO_KEYBOARD)
50		putc(c);
51	if (ioctrl & IO_SERIAL)
52		sio_putc(c);
53}
54
55void
56putchar(int c)
57{
58
59	if (c == '\n')
60		xputc('\r');
61	xputc(c);
62}
63
64int
65getc(int fn)
66{
67
68	/*
69	 * The extra comparison against zero is an attempt to work around
70	 * what appears to be a bug in QEMU and Bochs. Both emulators
71	 * sometimes report a key-press with scancode one and ascii zero
72	 * when no such key is pressed in reality. As far as I can tell,
73	 * this only happens shortly after a reboot.
74	 */
75	v86.ctl = V86_FLAGS;
76	v86.addr = 0x16;
77	v86.eax = fn << 8;
78	v86int();
79	return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff));
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;
110
111	if (OPT_CHECK(RBX_NOINTR))
112		return (0);
113	secs *= SECOND;
114	t0 = 0;
115	for (;;) {
116		if (xgetc(1))
117			return (1);
118		if (secs > 0) {
119			t1 = *(uint32_t *)PTOV(0x46c);
120			if (!t0)
121				t0 = t1;
122			if (t1 < t0 || t1 >= t0 + secs)
123				return (0);
124		}
125	}
126	/* NOTREACHED */
127}
128
129void
130getstr(char *cmdstr, size_t cmdstrsize)
131{
132	char *s;
133	int c;
134
135	s = cmdstr;
136	for (;;) {
137		switch (c = xgetc(0)) {
138		case 0:
139			break;
140		case '\177':
141		case '\b':
142			if (s > cmdstr) {
143				s--;
144				printf("\b \b");
145			}
146			break;
147		case '\n':
148		case '\r':
149			*s = 0;
150			return;
151		default:
152			if (s - cmdstr < cmdstrsize - 1)
153				*s++ = c;
154			putchar(c);
155			break;
156		}
157	}
158}
159