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/9/sys/boot/i386/common/cons.c 229501 2012-01-04 16:39:39Z jhb $");
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 
32 uint8_t ioctrl = IO_KEYBOARD;
33 
34 void
putc(int c)35 putc(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 
45 void
xputc(int c)46 xputc(int c)
47 {
48 
49 	if (ioctrl & IO_KEYBOARD)
50 		putc(c);
51 	if (ioctrl & IO_SERIAL)
52 		sio_putc(c);
53 }
54 
55 void
putchar(int c)56 putchar(int c)
57 {
58 
59 	if (c == '\n')
60 		xputc('\r');
61 	xputc(c);
62 }
63 
64 int
getc(int fn)65 getc(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 
82 int
xgetc(int fn)83 xgetc(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 
99 int
keyhit(unsigned int secs)100 keyhit(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 
122 void
getstr(char * cmdstr,size_t cmdstrsize)123 getstr(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