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
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
100keyhit(unsigned int secs)
101{
102	uint32_t t0, t1;
103
104	if (OPT_CHECK(RBX_NOINTR))
105		return (0);
106	secs *= SECOND;
107	t0 = 0;
108	for (;;) {
109		if (xgetc(1))
110			return (1);
111		if (secs > 0) {
112			t1 = *(uint32_t *)PTOV(0x46c);
113			if (!t0)
114				t0 = t1;
115			if (t1 < t0 || t1 >= t0 + secs)
116				return (0);
117		}
118	}
119	/* NOTREACHED */
120}
121
122void
123getstr(char *cmdstr, size_t cmdstrsize)
124{
125	char *s;
126	int c;
127
128	s = cmdstr;
129	for (;;) {
130		switch (c = xgetc(0)) {
131		case 0:
132			break;
133		case '\177':
134		case '\b':
135			if (s > cmdstr) {
136				s--;
137				printf("\b \b");
138			}
139			break;
140		case '\n':
141		case '\r':
142			*s = 0;
143			return;
144		default:
145			if (s - cmdstr < cmdstrsize - 1)
146				*s++ = c;
147			putchar(c);
148			break;
149		}
150	}
151}
152