freebsd-nq/stand/i386/common/cons.c
Toomas Soome 6469d2b422 boot2: need to expand tab output and mask getchar
The BIOS ouput char function does not expand tab.
Mask getchar with 0xFF.

Sponsored by:	Netflix, Klara Inc.
2020-06-16 20:35:00 +00:00

205 lines
3.1 KiB
C

/*-
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <machine/psl.h>
#include <btxv86.h>
#include "stand.h"
#include "lib.h"
#include "rbx.h"
#include "cons.h"
#define SECOND 18 /* Circa that many ticks in a second. */
uint8_t ioctrl = IO_KEYBOARD;
void
putc(int c)
{
v86.ctl = V86_FLAGS;
v86.addr = 0x10;
v86.eax = 0xe00 | (c & 0xff);
v86.ebx = 0x7;
v86int();
}
void
xputc(int c)
{
if (ioctrl & IO_KEYBOARD)
putc(c);
if (ioctrl & IO_SERIAL)
sio_putc(c);
}
static void
getcursor(int *row, int *col)
{
v86.ctl = V86_FLAGS;
v86.addr = 0x10;
v86.eax = 0x300;
v86.ebx = 0x7;
v86int();
if (row != NULL)
*row = v86.edx >> 8;
if (col != NULL)
*col = v86.edx & 0xff;
}
void
putchar(int c)
{
int i, col;
switch (c) {
case '\n':
xputc('\r');
break;
case '\t':
col = 0;
getcursor(NULL, &col);
col = 8 - (col % 8);
for (i = 0; i < col; i++)
xputc(' ');
return;
}
xputc(c);
}
int
getc(int fn)
{
v86.ctl = V86_FLAGS;
v86.addr = 0x16;
v86.eax = fn << 8;
v86int();
if (fn == 0)
return (v86.eax);
if (V86_ZR(v86.efl))
return (0);
return (v86.eax);
}
int
xgetc(int fn)
{
if (OPT_CHECK(RBX_NOINTR))
return (0);
for (;;) {
if (ioctrl & IO_KEYBOARD && getc(1))
return (fn ? 1 : getc(0));
if (ioctrl & IO_SERIAL && sio_ischar())
return (fn ? 1 : sio_getc());
if (fn)
return (0);
}
/* NOTREACHED */
}
int
getchar(void)
{
return (xgetc(0) & 0xff);
}
int
keyhit(unsigned int secs)
{
uint32_t t0, t1, c;
if (OPT_CHECK(RBX_NOINTR))
return (0);
secs *= SECOND;
t0 = 0;
for (;;) {
/*
* The extra comparison is an attempt to work around
* what appears to be a bug in QEMU and Bochs. Both emulators
* sometimes report a key-press with scancode one and ascii zero
* when no such key is pressed in reality. As far as I can tell,
* this only happens shortly after a reboot.
*/
c = xgetc(1);
if (c != 0 && c != 0x0100)
return (1);
if (secs > 0) {
t1 = *(uint32_t *)PTOV(0x46c);
if (!t0)
t0 = t1;
if (t1 < t0 || t1 >= t0 + secs)
return (0);
}
}
/* NOTREACHED */
}
void
getstr(char *cmdstr, size_t cmdstrsize)
{
char *s;
int c;
s = cmdstr;
for (;;) {
c = xgetc(0);
/* Translate some extended codes. */
switch (c) {
case 0x5300: /* delete */
c = '\177';
break;
default:
c &= 0xff;
break;
}
switch (c) {
case '\177':
case '\b':
if (s > cmdstr) {
s--;
printf("\b \b");
}
break;
case '\n':
case '\r':
*s = 0;
return;
default:
if (c >= 0x20 && c <= 0x7e) {
if (s - cmdstr < cmdstrsize - 1)
*s++ = c;
putchar(c);
}
break;
}
}
}