xref: /freebsd/stand/i386/common/cons.c (revision 6469d2b4)
1ca987d46SWarner Losh /*-
2ca987d46SWarner Losh  * Copyright (c) 1998 Robert Nordier
3ca987d46SWarner Losh  * All rights reserved.
4ca987d46SWarner Losh  *
5ca987d46SWarner Losh  * Redistribution and use in source and binary forms are freely
6ca987d46SWarner Losh  * permitted provided that the above copyright notice and this
7ca987d46SWarner Losh  * paragraph and the following disclaimer are duplicated in all
8ca987d46SWarner Losh  * such forms.
9ca987d46SWarner Losh  *
10ca987d46SWarner Losh  * This software is provided "AS IS" and without any express or
11ca987d46SWarner Losh  * implied warranties, including, without limitation, the implied
12ca987d46SWarner Losh  * warranties of merchantability and fitness for a particular
13ca987d46SWarner Losh  * purpose.
14ca987d46SWarner Losh  */
15ca987d46SWarner Losh 
16ca987d46SWarner Losh #include <sys/cdefs.h>
17ca987d46SWarner Losh __FBSDID("$FreeBSD$");
18ca987d46SWarner Losh 
19ca987d46SWarner Losh #include <sys/param.h>
20ca987d46SWarner Losh 
21ca987d46SWarner Losh #include <machine/psl.h>
22ca987d46SWarner Losh 
23ca987d46SWarner Losh #include <btxv86.h>
24ca987d46SWarner Losh 
2565628439SWarner Losh #include "stand.h"
2665628439SWarner Losh 
27ca987d46SWarner Losh #include "lib.h"
28ca987d46SWarner Losh #include "rbx.h"
29ca987d46SWarner Losh #include "cons.h"
30ca987d46SWarner Losh 
31ca987d46SWarner Losh #define SECOND		18	/* Circa that many ticks in a second. */
32ca987d46SWarner Losh 
33ca987d46SWarner Losh uint8_t ioctrl = IO_KEYBOARD;
34ca987d46SWarner Losh 
35ca987d46SWarner Losh void
36ca987d46SWarner Losh putc(int c)
37ca987d46SWarner Losh {
38ca987d46SWarner Losh 
39ca987d46SWarner Losh 	v86.ctl = V86_FLAGS;
40ca987d46SWarner Losh 	v86.addr = 0x10;
41ca987d46SWarner Losh 	v86.eax = 0xe00 | (c & 0xff);
42ca987d46SWarner Losh 	v86.ebx = 0x7;
43ca987d46SWarner Losh 	v86int();
44ca987d46SWarner Losh }
45ca987d46SWarner Losh 
46ca987d46SWarner Losh void
47ca987d46SWarner Losh xputc(int c)
48ca987d46SWarner Losh {
49ca987d46SWarner Losh 
50ca987d46SWarner Losh 	if (ioctrl & IO_KEYBOARD)
51ca987d46SWarner Losh 		putc(c);
52ca987d46SWarner Losh 	if (ioctrl & IO_SERIAL)
53ca987d46SWarner Losh 		sio_putc(c);
54ca987d46SWarner Losh }
55ca987d46SWarner Losh 
566469d2b4SToomas Soome static void
576469d2b4SToomas Soome getcursor(int *row, int *col)
586469d2b4SToomas Soome {
596469d2b4SToomas Soome 	v86.ctl = V86_FLAGS;
606469d2b4SToomas Soome 	v86.addr = 0x10;
616469d2b4SToomas Soome 	v86.eax = 0x300;
626469d2b4SToomas Soome 	v86.ebx = 0x7;
636469d2b4SToomas Soome 	v86int();
646469d2b4SToomas Soome 
656469d2b4SToomas Soome 	if (row != NULL)
666469d2b4SToomas Soome 		*row = v86.edx >> 8;
676469d2b4SToomas Soome 	if (col != NULL)
686469d2b4SToomas Soome 		*col = v86.edx & 0xff;
696469d2b4SToomas Soome }
706469d2b4SToomas Soome 
71ca987d46SWarner Losh void
72ca987d46SWarner Losh putchar(int c)
73ca987d46SWarner Losh {
746469d2b4SToomas Soome 	int i, col;
75ca987d46SWarner Losh 
766469d2b4SToomas Soome 	switch (c) {
776469d2b4SToomas Soome 	case '\n':
78ca987d46SWarner Losh 		xputc('\r');
796469d2b4SToomas Soome 		break;
806469d2b4SToomas Soome 	case '\t':
816469d2b4SToomas Soome 		col = 0;
826469d2b4SToomas Soome 		getcursor(NULL, &col);
836469d2b4SToomas Soome 		col = 8 - (col % 8);
846469d2b4SToomas Soome 		for (i = 0; i < col; i++)
856469d2b4SToomas Soome 			xputc(' ');
866469d2b4SToomas Soome 		return;
876469d2b4SToomas Soome 	}
88ca987d46SWarner Losh 	xputc(c);
89ca987d46SWarner Losh }
90ca987d46SWarner Losh 
91ca987d46SWarner Losh int
92ca987d46SWarner Losh getc(int fn)
93ca987d46SWarner Losh {
94ca987d46SWarner Losh 
95ca987d46SWarner Losh 	v86.ctl = V86_FLAGS;
96ca987d46SWarner Losh 	v86.addr = 0x16;
97ca987d46SWarner Losh 	v86.eax = fn << 8;
98ca987d46SWarner Losh 	v86int();
99ca987d46SWarner Losh 
100ca987d46SWarner Losh 	if (fn == 0)
101ca987d46SWarner Losh 		return (v86.eax);
102ca987d46SWarner Losh 
103ca987d46SWarner Losh 	if (V86_ZR(v86.efl))
104ca987d46SWarner Losh 		return (0);
105ca987d46SWarner Losh 	return (v86.eax);
106ca987d46SWarner Losh }
107ca987d46SWarner Losh 
108ca987d46SWarner Losh int
109ca987d46SWarner Losh xgetc(int fn)
110ca987d46SWarner Losh {
111ca987d46SWarner Losh 
112ca987d46SWarner Losh 	if (OPT_CHECK(RBX_NOINTR))
113ca987d46SWarner Losh 		return (0);
114ca987d46SWarner Losh 	for (;;) {
115ca987d46SWarner Losh 		if (ioctrl & IO_KEYBOARD && getc(1))
116ca987d46SWarner Losh 			return (fn ? 1 : getc(0));
117ca987d46SWarner Losh 		if (ioctrl & IO_SERIAL && sio_ischar())
118ca987d46SWarner Losh 			return (fn ? 1 : sio_getc());
119ca987d46SWarner Losh 		if (fn)
120ca987d46SWarner Losh 			return (0);
121ca987d46SWarner Losh 	}
122ca987d46SWarner Losh 	/* NOTREACHED */
123ca987d46SWarner Losh }
124ca987d46SWarner Losh 
125ca987d46SWarner Losh int
126ca987d46SWarner Losh getchar(void)
127ca987d46SWarner Losh {
128ca987d46SWarner Losh 
1296469d2b4SToomas Soome 	return (xgetc(0) & 0xff);
130ca987d46SWarner Losh }
131ca987d46SWarner Losh 
132ca987d46SWarner Losh int
133ca987d46SWarner Losh keyhit(unsigned int secs)
134ca987d46SWarner Losh {
135ca987d46SWarner Losh 	uint32_t t0, t1, c;
136ca987d46SWarner Losh 
137ca987d46SWarner Losh 	if (OPT_CHECK(RBX_NOINTR))
138ca987d46SWarner Losh 		return (0);
139ca987d46SWarner Losh 	secs *= SECOND;
140ca987d46SWarner Losh 	t0 = 0;
141ca987d46SWarner Losh 	for (;;) {
142ca987d46SWarner Losh 		/*
143ca987d46SWarner Losh 		 * The extra comparison is an attempt to work around
144ca987d46SWarner Losh 		 * what appears to be a bug in QEMU and Bochs. Both emulators
145ca987d46SWarner Losh 		 * sometimes report a key-press with scancode one and ascii zero
146ca987d46SWarner Losh 		 * when no such key is pressed in reality. As far as I can tell,
147ca987d46SWarner Losh 		 * this only happens shortly after a reboot.
148ca987d46SWarner Losh 		 */
149ca987d46SWarner Losh 		c = xgetc(1);
150ca987d46SWarner Losh 		if (c != 0 && c != 0x0100)
151ca987d46SWarner Losh 			return (1);
152ca987d46SWarner Losh 		if (secs > 0) {
153ca987d46SWarner Losh 			t1 = *(uint32_t *)PTOV(0x46c);
154ca987d46SWarner Losh 			if (!t0)
155ca987d46SWarner Losh 				t0 = t1;
156ca987d46SWarner Losh 			if (t1 < t0 || t1 >= t0 + secs)
157ca987d46SWarner Losh 				return (0);
158ca987d46SWarner Losh 		}
159ca987d46SWarner Losh 	}
160ca987d46SWarner Losh 	/* NOTREACHED */
161ca987d46SWarner Losh }
162ca987d46SWarner Losh 
163ca987d46SWarner Losh void
164ca987d46SWarner Losh getstr(char *cmdstr, size_t cmdstrsize)
165ca987d46SWarner Losh {
166ca987d46SWarner Losh 	char *s;
167ca987d46SWarner Losh 	int c;
168ca987d46SWarner Losh 
169ca987d46SWarner Losh 	s = cmdstr;
170ca987d46SWarner Losh 	for (;;) {
171ca987d46SWarner Losh 		c = xgetc(0);
172ca987d46SWarner Losh 
173ca987d46SWarner Losh 		/* Translate some extended codes. */
174ca987d46SWarner Losh 		switch (c) {
175ca987d46SWarner Losh 		case 0x5300:    /* delete */
176ca987d46SWarner Losh 			c = '\177';
177ca987d46SWarner Losh 			break;
178ca987d46SWarner Losh 		default:
179ca987d46SWarner Losh 			c &= 0xff;
180ca987d46SWarner Losh 			break;
181ca987d46SWarner Losh 		}
182ca987d46SWarner Losh 
183ca987d46SWarner Losh 		switch (c) {
184ca987d46SWarner Losh 		case '\177':
185ca987d46SWarner Losh 		case '\b':
186ca987d46SWarner Losh 			if (s > cmdstr) {
187ca987d46SWarner Losh 				s--;
188ca987d46SWarner Losh 				printf("\b \b");
189ca987d46SWarner Losh 			}
190ca987d46SWarner Losh 			break;
191ca987d46SWarner Losh 		case '\n':
192ca987d46SWarner Losh 		case '\r':
193ca987d46SWarner Losh 			*s = 0;
194ca987d46SWarner Losh 			return;
195ca987d46SWarner Losh 		default:
196ca987d46SWarner Losh 			if (c >= 0x20 && c <= 0x7e) {
197ca987d46SWarner Losh 				if (s - cmdstr < cmdstrsize - 1)
198ca987d46SWarner Losh 					*s++ = c;
199ca987d46SWarner Losh 				putchar(c);
200ca987d46SWarner Losh 			}
201ca987d46SWarner Losh 			break;
202ca987d46SWarner Losh 		}
203ca987d46SWarner Losh 	}
204ca987d46SWarner Losh }
205