cons.c revision 213136
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: head/sys/boot/i386/common/cons.c 213136 2010-09-24 19:49:12Z pjd $");
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	V86_ZR(x)	((x) & PSL_Z)
31
32#define SECOND		18	/* Circa that many ticks in a second. */
33
34uint8_t ioctrl = IO_KEYBOARD;
35
36void
37putc(int c)
38{
39
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	/*
70	 * The extra comparison against zero is an attempt to work around
71	 * what appears to be a bug in QEMU and Bochs. Both emulators
72	 * sometimes report a key-press with scancode one and ascii zero
73	 * when no such key is pressed in reality. As far as I can tell,
74	 * this only happens shortly after a reboot.
75	 */
76	v86.ctl = V86_FLAGS;
77	v86.addr = 0x16;
78	v86.eax = fn << 8;
79	v86int();
80	return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff));
81}
82
83int
84xgetc(int fn)
85{
86
87	if (OPT_CHECK(RBX_NOINTR))
88		return (0);
89	for (;;) {
90		if (ioctrl & IO_KEYBOARD && getc(1))
91			return (fn ? 1 : getc(0));
92		if (ioctrl & IO_SERIAL && sio_ischar())
93			return (fn ? 1 : sio_getc());
94		if (fn)
95			return (0);
96	}
97	/* NOTREACHED */
98}
99
100int
101keyhit(unsigned int secs)
102{
103	uint32_t t0, t1;
104
105	if (OPT_CHECK(RBX_NOINTR))
106		return (0);
107	secs *= SECOND;
108	t0 = 0;
109	for (;;) {
110		if (xgetc(1))
111			return (1);
112		if (secs > 0) {
113			t1 = *(uint32_t *)PTOV(0x46c);
114			if (!t0)
115				t0 = t1;
116			if (t1 < t0 || t1 >= t0 + secs)
117				return (0);
118		}
119	}
120	/* NOTREACHED */
121}
122
123void
124getstr(char *cmdstr, size_t cmdstrsize)
125{
126	char *s;
127	int c;
128
129	s = cmdstr;
130	for (;;) {
131		switch (c = xgetc(0)) {
132		case 0:
133			break;
134		case '\177':
135		case '\b':
136			if (s > cmdstr) {
137				s--;
138				printf("\b \b");
139			}
140			break;
141		case '\n':
142		case '\r':
143			*s = 0;
144			return;
145		default:
146			if (s - cmdstr < cmdstrsize - 1)
147				*s++ = c;
148			putchar(c);
149			break;
150		}
151	}
152}
153