1213136Spjd/*-
2213136Spjd * Copyright (c) 1998 Robert Nordier
3213136Spjd * All rights reserved.
4213136Spjd *
5213136Spjd * Redistribution and use in source and binary forms are freely
6213136Spjd * permitted provided that the above copyright notice and this
7213136Spjd * paragraph and the following disclaimer are duplicated in all
8213136Spjd * such forms.
9213136Spjd *
10213136Spjd * This software is provided "AS IS" and without any express or
11213136Spjd * implied warranties, including, without limitation, the implied
12213136Spjd * warranties of merchantability and fitness for a particular
13213136Spjd * purpose.
14213136Spjd */
15213136Spjd
16213136Spjd#include <sys/cdefs.h>
17213136Spjd__FBSDID("$FreeBSD$");
18213136Spjd
19213136Spjd#include <sys/param.h>
20213136Spjd
21213136Spjd#include <machine/psl.h>
22213136Spjd
23213136Spjd#include <btxv86.h>
24213136Spjd
25213136Spjd#include "lib.h"
26213136Spjd#include "rbx.h"
27213136Spjd#include "util.h"
28213136Spjd#include "cons.h"
29213136Spjd
30213136Spjd#define SECOND		18	/* Circa that many ticks in a second. */
31213136Spjd
32213136Spjduint8_t ioctrl = IO_KEYBOARD;
33213136Spjd
34213136Spjdvoid
35213136Spjdputc(int c)
36213136Spjd{
37213136Spjd
38219702Sae	v86.ctl = V86_FLAGS;
39213136Spjd	v86.addr = 0x10;
40213136Spjd	v86.eax = 0xe00 | (c & 0xff);
41213136Spjd	v86.ebx = 0x7;
42213136Spjd	v86int();
43213136Spjd}
44213136Spjd
45213136Spjdvoid
46213136Spjdxputc(int c)
47213136Spjd{
48213136Spjd
49213136Spjd	if (ioctrl & IO_KEYBOARD)
50213136Spjd		putc(c);
51213136Spjd	if (ioctrl & IO_SERIAL)
52213136Spjd		sio_putc(c);
53213136Spjd}
54213136Spjd
55213136Spjdvoid
56213136Spjdputchar(int c)
57213136Spjd{
58213136Spjd
59213136Spjd	if (c == '\n')
60213136Spjd		xputc('\r');
61213136Spjd	xputc(c);
62213136Spjd}
63213136Spjd
64213136Spjdint
65213136Spjdgetc(int fn)
66213136Spjd{
67213136Spjd
68213136Spjd	/*
69213136Spjd	 * The extra comparison against zero is an attempt to work around
70213136Spjd	 * what appears to be a bug in QEMU and Bochs. Both emulators
71213136Spjd	 * sometimes report a key-press with scancode one and ascii zero
72213136Spjd	 * when no such key is pressed in reality. As far as I can tell,
73213136Spjd	 * this only happens shortly after a reboot.
74213136Spjd	 */
75213136Spjd	v86.ctl = V86_FLAGS;
76213136Spjd	v86.addr = 0x16;
77213136Spjd	v86.eax = fn << 8;
78213136Spjd	v86int();
79213136Spjd	return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff));
80213136Spjd}
81213136Spjd
82213136Spjdint
83213136Spjdxgetc(int fn)
84213136Spjd{
85213136Spjd
86213136Spjd	if (OPT_CHECK(RBX_NOINTR))
87213136Spjd		return (0);
88213136Spjd	for (;;) {
89213136Spjd		if (ioctrl & IO_KEYBOARD && getc(1))
90213136Spjd			return (fn ? 1 : getc(0));
91213136Spjd		if (ioctrl & IO_SERIAL && sio_ischar())
92213136Spjd			return (fn ? 1 : sio_getc());
93213136Spjd		if (fn)
94213136Spjd			return (0);
95213136Spjd	}
96213136Spjd	/* NOTREACHED */
97213136Spjd}
98213136Spjd
99213136Spjdint
100213136Spjdkeyhit(unsigned int secs)
101213136Spjd{
102213136Spjd	uint32_t t0, t1;
103213136Spjd
104213136Spjd	if (OPT_CHECK(RBX_NOINTR))
105213136Spjd		return (0);
106213136Spjd	secs *= SECOND;
107213136Spjd	t0 = 0;
108213136Spjd	for (;;) {
109213136Spjd		if (xgetc(1))
110213136Spjd			return (1);
111213136Spjd		if (secs > 0) {
112213136Spjd			t1 = *(uint32_t *)PTOV(0x46c);
113213136Spjd			if (!t0)
114213136Spjd				t0 = t1;
115213136Spjd			if (t1 < t0 || t1 >= t0 + secs)
116213136Spjd				return (0);
117213136Spjd		}
118213136Spjd	}
119213136Spjd	/* NOTREACHED */
120213136Spjd}
121213136Spjd
122213136Spjdvoid
123213136Spjdgetstr(char *cmdstr, size_t cmdstrsize)
124213136Spjd{
125213136Spjd	char *s;
126213136Spjd	int c;
127213136Spjd
128213136Spjd	s = cmdstr;
129213136Spjd	for (;;) {
130213136Spjd		switch (c = xgetc(0)) {
131213136Spjd		case 0:
132213136Spjd			break;
133213136Spjd		case '\177':
134213136Spjd		case '\b':
135213136Spjd			if (s > cmdstr) {
136213136Spjd				s--;
137213136Spjd				printf("\b \b");
138213136Spjd			}
139213136Spjd			break;
140213136Spjd		case '\n':
141213136Spjd		case '\r':
142213136Spjd			*s = 0;
143213136Spjd			return;
144213136Spjd		default:
145213136Spjd			if (s - cmdstr < cmdstrsize - 1)
146213136Spjd				*s++ = c;
147213136Spjd			putchar(c);
148213136Spjd			break;
149213136Spjd		}
150213136Spjd	}
151213136Spjd}
152