vidconsole.c revision 146011
1146011Snyan/*-
243561Skato * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
343561Skato * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
443561Skato * All rights reserved.
543561Skato *
643561Skato * Redistribution and use in source and binary forms, with or without
743561Skato * modification, are permitted provided that the following conditions
843561Skato * are met:
943561Skato * 1. Redistributions of source code must retain the above copyright
1043561Skato *    notice, this list of conditions and the following disclaimer.
1143561Skato * 2. Redistributions in binary form must reproduce the above copyright
1243561Skato *    notice, this list of conditions and the following disclaimer in the
1343561Skato *    documentation and/or other materials provided with the distribution.
1443561Skato *
1543561Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1643561Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1743561Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1843561Skato * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1943561Skato * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2043561Skato * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2143561Skato * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2243561Skato * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2343561Skato * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2443561Skato * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2543561Skato * SUCH DAMAGE.
2643561Skato *
27119880Sobrien * 	Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
2843561Skato */
2943561Skato
30119880Sobrien#include <sys/cdefs.h>
31119880Sobrien__FBSDID("$FreeBSD: head/sys/boot/pc98/libpc98/vidconsole.c 146011 2005-05-08 14:17:28Z nyan $");
32119880Sobrien
3343561Skato#include <stand.h>
3443561Skato#include <bootstrap.h>
3543561Skato#include <btxv86.h>
3643561Skato#include <machine/psl.h>
3743561Skato#include <machine/cpufunc.h>
3868358Snyan#include "libi386.h"
3943561Skato
4043561Skato#if KEYBOARD_PROBE
4143561Skato#include <machine/cpufunc.h>
4243561Skato
4343561Skatostatic int	probe_keyboard(void);
4443561Skato#endif
4543561Skatostatic void	vidc_probe(struct console *cp);
4643561Skatostatic int	vidc_init(int arg);
4743561Skatostatic void	vidc_putchar(int c);
4843561Skatostatic int	vidc_getchar(void);
4943561Skatostatic int	vidc_ischar(void);
5043561Skato
5143561Skatostatic int	vidc_started;
5243561Skato
5343561Skato#ifdef TERM_EMU
5485063Snyan#define MAXARGS		8
5585063Snyan#define DEFAULT_FGCOLOR	7
5685063Snyan#define DEFAULT_BGCOLOR	0
5785063Snyan
5868358Snyanvoid		end_term(void);
5943561Skatovoid		bail_out(int c);
6043561Skatovoid		vidc_term_emu(int c);
6143561Skatovoid		get_pos(void);
6243561Skatovoid		curs_move(int x, int y);
6343561Skatovoid		write_char(int c, int fg, int bg);
6443561Skatovoid		scroll_up(int rows, int fg, int bg);
6543561Skatovoid		CD(void);
6643561Skatovoid		CM(void);
6743561Skatovoid		HO(void);
6843561Skato
6985063Snyanstatic int	args[MAXARGS], argc;
7085063Snyanstatic int	fg_c, bg_c, curx, cury;
7143561Skatostatic int	esc;
7243561Skato#endif
7343561Skato
7443561Skatostatic unsigned short *crtat, *Crtat;
7543561Skatostatic int row = 25, col = 80;
7643561Skato#ifdef TERM_EMU
7785065Snyanstatic u_int8_t	ibmpc_to_pc98[256] = {
7885065Snyan	0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1,
7985065Snyan	0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9,
8085065Snyan	0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
8185065Snyan	0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
8285065Snyan	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
8385065Snyan	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
8485065Snyan	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
8585065Snyan	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
8685065Snyan	0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
8785065Snyan	0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
8885065Snyan	0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
8985065Snyan	0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
9085065Snyan	0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
9185065Snyan	0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
9285065Snyan	0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
9385065Snyan	0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
9443561Skato
9585065Snyan	0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3,
9685065Snyan	0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb,
9785065Snyan	0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
9885065Snyan	0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
9985065Snyan	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
10085065Snyan	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
10185065Snyan	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
10285065Snyan	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
10385065Snyan	0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
10485065Snyan	0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
10585065Snyan	0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
10685065Snyan	0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
10785065Snyan	0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
10885065Snyan	0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
10985065Snyan	0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
11085065Snyan	0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
11185065Snyan};
11285065Snyan#define	at2pc98(fg_at, bg_at)	ibmpc_to_pc98[((bg_at) << 4) | (fg_at)]
11385065Snyan#endif /* TERM_EMU */
11485065Snyan
11543561Skatostruct console vidconsole = {
11643561Skato    "vidconsole",
11743561Skato    "internal video/keyboard",
11843561Skato    0,
11943561Skato    vidc_probe,
12043561Skato    vidc_init,
12143561Skato    vidc_putchar,
12243561Skato    vidc_getchar,
12343561Skato    vidc_ischar
12443561Skato};
12543561Skato
12643561Skatostatic void
12743561Skatovidc_probe(struct console *cp)
12843561Skato{
12943561Skato
13043561Skato    /* look for a keyboard */
13143561Skato#if KEYBOARD_PROBE
13243561Skato    if (probe_keyboard())
13343561Skato#endif
13443561Skato    {
13543561Skato
13643561Skato	cp->c_flags |= C_PRESENTIN;
13743561Skato    }
13843561Skato
13943561Skato    /* XXX for now, always assume we can do BIOS screen output */
14043561Skato    cp->c_flags |= C_PRESENTOUT;
14143561Skato}
14243561Skato
14343561Skatostatic int
14443561Skatovidc_init(int arg)
14543561Skato{
146146011Snyan    int		i, hw_cursor;
14743561Skato
14843561Skato    if (vidc_started && arg == 0)
14985061Snyan	return (0);
15043561Skato    vidc_started = 1;
15143561Skato    Crtat = (unsigned short *)PTOV(0xA0000);
15285061Snyan    while ((inb(0x60) & 0x04) == 0)
15385061Snyan	;
15443561Skato    outb(0x62, 0xe0);
15585061Snyan    while ((inb(0x60) & 0x01) == 0)
15685061Snyan	;
15743561Skato    hw_cursor = inb(0x62);
15843561Skato    hw_cursor |= (inb(0x62) << 8);
15943561Skato    inb(0x62);
16043561Skato    inb(0x62);
16143561Skato    inb(0x62);
16243561Skato    crtat = Crtat + hw_cursor;
16343561Skato#ifdef TERM_EMU
16443561Skato    /* Init terminal emulator */
16543561Skato    end_term();
16643561Skato    get_pos();
16785061Snyan    curs_move(curx, cury);
16885063Snyan    fg_c = DEFAULT_FGCOLOR;
16985063Snyan    bg_c = DEFAULT_BGCOLOR;
17043561Skato#endif
17185061Snyan    for (i = 0; i < 10 && vidc_ischar(); i++)
17285061Snyan	(void)vidc_getchar();
17385061Snyan    return (0);	/* XXX reinit? */
17443561Skato}
17543561Skato
17643561Skatostatic void
17754086Snyanbeep(void)
17854086Snyan{
17985061Snyan
18054086Snyan	outb(0x37, 6);
18154086Snyan	delay(40000);
18254086Snyan	outb(0x37, 7);
18354086Snyan}
18454086Snyan
18554086Snyan#if 0
18654086Snyanstatic void
18743561Skatovidc_biosputchar(int c)
18843561Skato{
18943561Skato    unsigned short *cp;
19043561Skato    int i, pos;
19143561Skato
19243561Skato#ifdef TERM_EMU
19343561Skato    *crtat = (c == 0x5c ? 0xfc : c);
19443561Skato    *(crtat + 0x1000) = at2pc98(fg, bg);
19543561Skato#else
19643561Skato    switch(c) {
19743561Skato    case '\b':
19843561Skato        crtat--;
19943561Skato	break;
20043561Skato    case '\r':
20143561Skato        crtat -= (crtat - Crtat) % col;
20243561Skato	break;
20343561Skato    case '\n':
20443561Skato        crtat += col;
20543561Skato	break;
20643561Skato    default:
20743561Skato        *crtat = (c == 0x5c ? 0xfc : c);
20843561Skato	*(crtat++ + 0x1000) = 0xe1;
20943561Skato	break;
21043561Skato    }
21143561Skato
21243561Skato    if (crtat >= Crtat + col * row) {
21343561Skato        cp = Crtat;
21443561Skato	for (i = 1; i < row; i++) {
21585061Snyan	    bcopy((void *)(cp + col), (void *)cp, col * 2);
21643561Skato	    cp += col;
21743561Skato	}
21843561Skato	for (i = 0; i < col; i++) {
21943561Skato	    *cp++ = ' ';
22043561Skato	}
22143561Skato	crtat -= col;
22243561Skato    }
22343561Skato    pos = crtat - Crtat;
22485061Snyan    while ((inb(0x60) & 0x04) == 0) {}
22543561Skato    outb(0x62, 0x49);
22643561Skato    outb(0x60, pos & 0xff);
22743561Skato    outb(0x60, pos >> 8);
22843561Skato#endif
22943561Skato}
23054086Snyan#endif
23143561Skato
23243561Skatostatic void
23343561Skatovidc_rawputchar(int c)
23443561Skato{
23543561Skato    int		i;
23643561Skato
23785061Snyan    if (c == '\t')
23843561Skato	/* lame tab expansion */
23943561Skato	for (i = 0; i < 8; i++)
24043561Skato	    vidc_rawputchar(' ');
24143561Skato    else {
24243561Skato	/* Emulate AH=0eh (teletype output) */
24343561Skato	switch(c) {
24443561Skato	case '\a':
24585061Snyan	    beep();
24685061Snyan	    return;
24743561Skato	case '\r':
24885061Snyan	    curx = 0;
24985061Snyan	    curs_move(curx, cury);
25085061Snyan	    return;
25143561Skato	case '\n':
25285061Snyan	    cury++;
25385061Snyan	    if (cury > 24) {
25485061Snyan		scroll_up(1, fg_c, bg_c);
25585061Snyan		cury--;
25685061Snyan	    } else {
25785061Snyan		curs_move(curx, cury);
25885061Snyan	    }
25985061Snyan	    return;
26043561Skato	case '\b':
26185061Snyan	    if (curx > 0) {
26285061Snyan		curx--;
26385061Snyan		curs_move(curx, cury);
26485061Snyan		/* write_char(' ', fg_c, bg_c); XXX destructive(!) */
26543561Skato		return;
26685061Snyan	    }
26785061Snyan	    return;
26843561Skato	default:
26985061Snyan	    write_char(c, fg_c, bg_c);
27085061Snyan	    curx++;
27185061Snyan	    if (curx > 79) {
27285061Snyan		curx = 0;
27385061Snyan		cury++;
27485061Snyan	    }
27585061Snyan	    if (cury > 24) {
27685061Snyan		curx = 0;
27785061Snyan		scroll_up(1, fg_c, bg_c);
27885061Snyan		cury--;
27985061Snyan	    }
28043561Skato	}
28185061Snyan	curs_move(curx, cury);
28243561Skato    }
28343561Skato}
28443561Skato
28543561Skato#ifdef TERM_EMU
28643561Skato
28743561Skato/* Get cursor position on the screen. Result is in edx. Sets
28843561Skato * curx and cury appropriately.
28943561Skato */
29043561Skatovoid
29143561Skatoget_pos(void)
29243561Skato{
29343561Skato    int pos = crtat - Crtat;
29485061Snyan
29543561Skato    curx = pos % col;
29643561Skato    cury = pos / col;
29743561Skato}
29843561Skato
29943561Skato/* Move cursor to x rows and y cols (0-based). */
30043561Skatovoid
30143561Skatocurs_move(int x, int y)
30243561Skato{
30343561Skato    int pos;
30485061Snyan
30585061Snyan    pos = x + y * col;
30643561Skato    crtat = Crtat + pos;
30743561Skato    pos = crtat - Crtat;
30843561Skato    while((inb(0x60) & 0x04) == 0) {}
30943561Skato    outb(0x62, 0x49);
31043561Skato    outb(0x60, pos & 0xff);
31143561Skato    outb(0x60, pos >> 8);
31285061Snyan    curx = x;
31385061Snyan    cury = y;
31485063Snyan#define isvisible(c)	(((c) >= 32) && ((c) < 255))
31585061Snyan    if (!isvisible(*crtat & 0x00ff)) {
31685061Snyan	write_char(' ', fg_c, bg_c);
31743561Skato    }
31843561Skato}
31943561Skato
32043561Skato/* Scroll up the whole window by a number of rows. If rows==0,
32143561Skato * clear the window. fg and bg are attributes for the new lines
32243561Skato * inserted in the window.
32343561Skato */
32443561Skatovoid
32568358Snyanscroll_up(int rows, int fgcol, int bgcol)
32643561Skato{
32785061Snyan    unsigned short *cp;
32885061Snyan    int i;
32943561Skato
33085061Snyan    if (rows == 0)
33185061Snyan	rows = 25;
33285061Snyan    cp = Crtat;
33385061Snyan    for (i = rows; i < row; i++) {
33485061Snyan	bcopy((void *)(cp + col), (void *)cp, col * 2);
33585061Snyan	cp += col;
33685061Snyan    }
33785061Snyan    for (i = 0; i < col; i++) {
33885061Snyan	*(cp + 0x1000) = at2pc98(fgcol, bgcol);
33985061Snyan	*cp++ = ' ';
34085061Snyan    }
34143561Skato}
34243561Skato
34343561Skato/* Write character and attribute at cursor position. */
34443561Skatovoid
34568358Snyanwrite_char(int c, int fgcol, int bgcol)
34643561Skato{
34785061Snyan
348124647Snyan    *crtat = (c == 0x5c ? 0xfc : (c & 0xff));
34985061Snyan    *(crtat + 0x1000) = at2pc98(fgcol, bgcol);
35043561Skato}
35143561Skato
35243561Skato/**************************************************************/
35343561Skato/*
35443561Skato * Screen manipulation functions. They use accumulated data in
35543561Skato * args[] and argc variables.
35643561Skato *
35743561Skato */
35843561Skato
35943561Skato/* Clear display from current position to end of screen */
36043561Skatovoid
36143561SkatoCD(void)
36243561Skato{
36385063Snyan    int pos;
36485061Snyan
36543561Skato    get_pos();
36685063Snyan    for (pos = 0; crtat + pos <= Crtat + col * row; pos++) {
36785063Snyan	*(crtat + pos) = ' ';
36885063Snyan	*(crtat + pos + 0x1000) = at2pc98(fg_c, bg_c);
36943561Skato    }
37085063Snyan    end_term();
37143561Skato}
37243561Skato
37343561Skato/* Absolute cursor move to args[0] rows and args[1] columns
37443561Skato * (the coordinates are 1-based).
37543561Skato */
37643561Skatovoid
37743561SkatoCM(void)
37843561Skato{
37985061Snyan
38085061Snyan    if (args[0] > 0)
38185061Snyan	args[0]--;
38285061Snyan    if (args[1] > 0)
38385061Snyan	args[1]--;
38485061Snyan    curs_move(args[1], args[0]);
38543561Skato    end_term();
38643561Skato}
38743561Skato
38843561Skato/* Home cursor (left top corner) */
38943561Skatovoid
39043561SkatoHO(void)
39143561Skato{
39285061Snyan
39385061Snyan    argc = 1;
39485061Snyan    args[0] = args[1] = 1;
39585061Snyan    CM();
39643561Skato}
39743561Skato
39843561Skato/* Clear internal state of the terminal emulation code */
39943561Skatovoid
40043561Skatoend_term(void)
40143561Skato{
40285061Snyan
40385061Snyan    esc = 0;
40485061Snyan    argc = -1;
40543561Skato}
40643561Skato
40743561Skato/* Gracefully exit ESC-sequence processing in case of misunderstanding */
40843561Skatovoid
40943561Skatobail_out(int c)
41043561Skato{
41185063Snyan    char buf[16], *ch;
41285063Snyan    int i;
41343561Skato
41485063Snyan    if (esc) {
41585061Snyan	vidc_rawputchar('\033');
41685063Snyan	if (esc != '\033')
41785063Snyan	    vidc_rawputchar(esc);
41885063Snyan	for (i = 0; i <= argc; ++i) {
41985063Snyan	    sprintf(buf, "%d", args[i]);
42085061Snyan	    ch = buf;
42185061Snyan	    while (*ch)
42285061Snyan		vidc_rawputchar(*ch++);
42343561Skato	}
42485061Snyan    }
42585061Snyan    vidc_rawputchar(c);
42685061Snyan    end_term();
42743561Skato}
42843561Skato
42985063Snyanstatic void
430145069Snyanget_arg(int c)
43185063Snyan{
43285063Snyan
43385063Snyan    if (argc < 0)
43485063Snyan	argc = 0;
43585063Snyan    args[argc] *= 10;
43685063Snyan    args[argc] += c - '0';
43785063Snyan}
43885063Snyan
43943561Skato/* Emulate basic capabilities of cons25 terminal */
44043561Skatovoid
44143561Skatovidc_term_emu(int c)
44243561Skato{
44385063Snyan    static int ansi_col[] = {
44485063Snyan	0, 4, 2, 6, 1, 5, 3, 7,
44585063Snyan    };
44685063Snyan    int t;
44785063Snyan    int i;
44843561Skato
44985063Snyan    switch (esc) {
45085063Snyan    case 0:
45185063Snyan	switch (c) {
45285063Snyan	case '\033':
45385063Snyan	    esc = c;
45485063Snyan	    break;
45585063Snyan	default:
45643561Skato	    vidc_rawputchar(c);
45785063Snyan	    break;
45843561Skato	}
45985063Snyan	break;
46043561Skato
46143561Skato    case '\033':
46285063Snyan	switch (c) {
46385063Snyan	case '[':
46485063Snyan	    esc = c;
46585063Snyan	    args[0] = 0;
46685063Snyan	    argc = -1;
46785063Snyan	    break;
46885063Snyan	default:
46985063Snyan	    bail_out(c);
47085063Snyan	    break;
47185063Snyan	}
47243561Skato	break;
47385063Snyan
47443561Skato    case '[':
47585063Snyan	switch (c) {
47685063Snyan	case ';':
47785063Snyan	    if (argc < 0)	/* XXX */
47885063Snyan		argc = 0;
47985063Snyan	    else if (argc + 1 >= MAXARGS)
48085063Snyan		bail_out(c);
48185063Snyan	    else
48285063Snyan		args[++argc] = 0;
48385063Snyan	    break;
48485063Snyan	case 'H':
48585063Snyan	    if (argc < 0)
48643561Skato		HO();
48785063Snyan	    else if (argc == 1)
48843561Skato		CM();
48985063Snyan	    else
49043561Skato		bail_out(c);
49185063Snyan	    break;
49285063Snyan	case 'J':
49385063Snyan	    if (argc < 0)
49485063Snyan		CD();
49585063Snyan	    else
49685063Snyan		bail_out(c);
49785063Snyan	    break;
49885063Snyan	case 'm':
49985063Snyan	    if (argc < 0) {
50085063Snyan		fg_c = DEFAULT_FGCOLOR;
50185063Snyan		bg_c = DEFAULT_BGCOLOR;
50243561Skato	    }
50385063Snyan	    for (i = 0; i <= argc; ++i) {
50485063Snyan		switch (args[i]) {
50585063Snyan		case 0:		/* back to normal */
50685063Snyan		    fg_c = DEFAULT_FGCOLOR;
50785063Snyan		    bg_c = DEFAULT_BGCOLOR;
50885063Snyan		    break;
50985063Snyan		case 1:		/* bold */
51085063Snyan		    fg_c |= 0x8;
51185063Snyan		    break;
51285063Snyan		case 4:		/* underline */
51385063Snyan		case 5:		/* blink */
51485063Snyan		    bg_c |= 0x8;
51585063Snyan		    break;
51685063Snyan		case 7:		/* reverse */
51785063Snyan		    t = fg_c;
51885063Snyan		    fg_c = bg_c;
51985063Snyan		    bg_c = t;
52085063Snyan		    break;
52185063Snyan		case 30: case 31: case 32: case 33:
52285063Snyan		case 34: case 35: case 36: case 37:
52385063Snyan		    fg_c = ansi_col[args[i] - 30];
52485063Snyan		    break;
52585063Snyan		case 39:	/* normal */
52685063Snyan		    fg_c = DEFAULT_FGCOLOR;
52785063Snyan		    break;
52885063Snyan		case 40: case 41: case 42: case 43:
52985063Snyan		case 44: case 45: case 46: case 47:
53085063Snyan		    bg_c = ansi_col[args[i] - 40];
53185063Snyan		    break;
53285063Snyan		case 49:	/* normal */
53385063Snyan		    bg_c = DEFAULT_BGCOLOR;
53485063Snyan		    break;
53585063Snyan		}
53685063Snyan	    }
53785063Snyan	    end_term();
53885063Snyan	    break;
53985063Snyan	default:
54085063Snyan	    if (isdigit(c))
54185063Snyan		get_arg(c);
54285063Snyan	    else
54343561Skato		bail_out(c);
54485063Snyan	    break;
54585063Snyan	}
54643561Skato	break;
54785063Snyan
54843561Skato    default:
54985063Snyan	bail_out(c);
55043561Skato	break;
55143561Skato    }
55243561Skato}
55343561Skato#endif
55443561Skato
55543561Skatostatic void
55643561Skatovidc_putchar(int c)
55743561Skato{
55843561Skato#ifdef TERM_EMU
55943561Skato    vidc_term_emu(c);
56043561Skato#else
56143561Skato    vidc_rawputchar(c);
56243561Skato#endif
56343561Skato}
56443561Skato
56543561Skatostatic int
56643561Skatovidc_getchar(void)
56743561Skato{
56885061Snyan
56943561Skato    if (vidc_ischar()) {
57043561Skato	v86.ctl = 0;
57143561Skato	v86.addr = 0x18;
57243561Skato	v86.eax = 0x0;
57343561Skato	v86int();
57485061Snyan	return (v86.eax & 0xff);
57543561Skato    } else {
57685061Snyan	return (-1);
57743561Skato    }
57843561Skato}
57943561Skato
58043561Skatostatic int
58143561Skatovidc_ischar(void)
58243561Skato{
58385061Snyan
58443561Skato    v86.ctl = 0;
58543561Skato    v86.addr = 0x18;
58643561Skato    v86.eax = 0x100;
58743561Skato    v86int();
58885061Snyan    return ((v86.ebx >> 8) & 0x1);
58943561Skato}
59043561Skato
59143561Skato#if KEYBOARD_PROBE
59243561Skatostatic int
59343561Skatoprobe_keyboard(void)
59443561Skato{
59543561Skato    return (*(u_char *)PTOV(0xA1481) & 0x48);
59643561Skato}
59743561Skato#endif /* KEYBOARD_PROBE */
598