1119482Sobrien/*-
238465Smsmith * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
338465Smsmith * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
438465Smsmith * All rights reserved.
538465Smsmith *
638465Smsmith * Redistribution and use in source and binary forms, with or without
738465Smsmith * modification, are permitted provided that the following conditions
838465Smsmith * are met:
938465Smsmith * 1. Redistributions of source code must retain the above copyright
1038465Smsmith *    notice, this list of conditions and the following disclaimer.
1138465Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1238465Smsmith *    notice, this list of conditions and the following disclaimer in the
1338465Smsmith *    documentation and/or other materials provided with the distribution.
1438465Smsmith *
1538465Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1638465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1738465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1838465Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1938465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2038465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2138465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2238465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2338465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2438465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2538465Smsmith * SUCH DAMAGE.
2638465Smsmith *
27119482Sobrien * 	Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
2838465Smsmith */
2938465Smsmith
30119482Sobrien#include <sys/cdefs.h>
31119482Sobrien__FBSDID("$FreeBSD$");
32119482Sobrien
3338465Smsmith#include <stand.h>
3439441Smsmith#include <bootstrap.h>
3539441Smsmith#include <btxv86.h>
3640016Smsmith#include <machine/psl.h>
3739441Smsmith#include "libi386.h"
3838465Smsmith
3939441Smsmith#if KEYBOARD_PROBE
4038465Smsmith#include <machine/cpufunc.h>
4138465Smsmith
4238465Smsmithstatic int	probe_keyboard(void);
4339441Smsmith#endif
4438465Smsmithstatic void	vidc_probe(struct console *cp);
4538465Smsmithstatic int	vidc_init(int arg);
4639441Smsmithstatic void	vidc_putchar(int c);
4739441Smsmithstatic int	vidc_getchar(void);
4839441Smsmithstatic int	vidc_ischar(void);
4938465Smsmith
5040212Speterstatic int	vidc_started;
5140212Speter
5242002Sabial#ifdef TERM_EMU
5384371Syokota#define MAXARGS		8
5484371Syokota#define DEFAULT_FGCOLOR	7
5584371Syokota#define DEFAULT_BGCOLOR	0
5684371Syokota
5764187Sjhbvoid		end_term(void);
5842002Sabialvoid		bail_out(int c);
5942002Sabialvoid		vidc_term_emu(int c);
60199855Ssobomaxvoid		get_pos(int *x, int *y);
61199855Ssobomaxvoid		curs_move(int *_x, int *_y, int x, int y);
6242002Sabialvoid		write_char(int c, int fg, int bg);
6342002Sabialvoid		scroll_up(int rows, int fg, int bg);
6442002Sabialvoid		CD(void);
6542002Sabialvoid		CM(void);
6642002Sabialvoid		HO(void);
6742002Sabial
6884371Syokotastatic int	args[MAXARGS], argc;
6984371Syokotastatic int	fg_c, bg_c, curx, cury;
7042002Sabialstatic int	esc;
7142002Sabial#endif
7242002Sabial
7342002Sabial
7438465Smsmithstruct console vidconsole = {
7538465Smsmith    "vidconsole",
7638465Smsmith    "internal video/keyboard",
7738465Smsmith    0,
7838465Smsmith    vidc_probe,
7938465Smsmith    vidc_init,
8039441Smsmith    vidc_putchar,
8139441Smsmith    vidc_getchar,
8239441Smsmith    vidc_ischar
8338465Smsmith};
8438465Smsmith
8538465Smsmithstatic void
8638465Smsmithvidc_probe(struct console *cp)
8738465Smsmith{
8838465Smsmith
8938465Smsmith    /* look for a keyboard */
9039441Smsmith#if KEYBOARD_PROBE
9139441Smsmith    if (probe_keyboard())
9238465Smsmith#endif
9339441Smsmith    {
9439441Smsmith
9538465Smsmith	cp->c_flags |= C_PRESENTIN;
9638465Smsmith    }
9738465Smsmith
9838465Smsmith    /* XXX for now, always assume we can do BIOS screen output */
9938465Smsmith    cp->c_flags |= C_PRESENTOUT;
10038465Smsmith}
10138465Smsmith
10238465Smsmithstatic int
10338465Smsmithvidc_init(int arg)
10438465Smsmith{
10540212Speter    int		i;
10640016Smsmith
10740212Speter    if (vidc_started && arg == 0)
10884276Syokota	return (0);
10940212Speter    vidc_started = 1;
11042002Sabial#ifdef TERM_EMU
11142002Sabial    /* Init terminal emulator */
11242002Sabial    end_term();
113199855Ssobomax    get_pos(&curx, &cury);
114199855Ssobomax    curs_move(&curx, &cury, curx, cury);
11584371Syokota    fg_c = DEFAULT_FGCOLOR;
11684371Syokota    bg_c = DEFAULT_BGCOLOR;
11742002Sabial#endif
11884276Syokota    for (i = 0; i < 10 && vidc_ischar(); i++)
11984276Syokota	(void)vidc_getchar();
12084276Syokota    return (0);	/* XXX reinit? */
12138465Smsmith}
12238465Smsmith
123199855Ssobomaxvoid
12442207Sabialvidc_biosputchar(int c)
12542207Sabial{
12684276Syokota
12742207Sabial    v86.ctl = 0;
12842207Sabial    v86.addr = 0x10;
12942291Speter    v86.eax = 0xe00 | (c & 0xff);
13042207Sabial    v86.ebx = 0x7;
13142207Sabial    v86int();
13242207Sabial}
13342207Sabial
13442207Sabialstatic void
13542002Sabialvidc_rawputchar(int c)
13639441Smsmith{
13740775Smsmith    int		i;
13840775Smsmith
13984276Syokota    if (c == '\t')
14040775Smsmith	/* lame tab expansion */
14140775Smsmith	for (i = 0; i < 8; i++)
14242002Sabial	    vidc_rawputchar(' ');
14342002Sabial    else {
14442002Sabial#ifndef TERM_EMU
14542207Sabial        vidc_biosputchar(c);
14642002Sabial#else
14742002Sabial	/* Emulate AH=0eh (teletype output) */
14842002Sabial	switch(c) {
14942207Sabial	case '\a':
15084276Syokota	    vidc_biosputchar(c);
15184276Syokota	    return;
15242002Sabial	case '\r':
15384276Syokota	    curx = 0;
154199855Ssobomax	    curs_move(&curx, &cury, curx, cury);
15584276Syokota	    return;
15642002Sabial	case '\n':
15784276Syokota	    cury++;
15884276Syokota	    if (cury > 24) {
15984276Syokota		scroll_up(1, fg_c, bg_c);
16084276Syokota		cury--;
16184276Syokota	    } else {
162199855Ssobomax		curs_move(&curx, &cury, curx, cury);
16384276Syokota	    }
16484276Syokota	    return;
16542002Sabial	case '\b':
16684276Syokota	    if (curx > 0) {
16784276Syokota		curx--;
168199855Ssobomax		curs_move(&curx, &cury, curx, cury);
16984276Syokota		/* write_char(' ', fg_c, bg_c); XXX destructive(!) */
17042002Sabial		return;
17184276Syokota	    }
17284276Syokota	    return;
17342002Sabial	default:
17484276Syokota	    write_char(c, fg_c, bg_c);
17584276Syokota	    curx++;
17684276Syokota	    if (curx > 79) {
17784276Syokota		curx = 0;
17884276Syokota		cury++;
17984276Syokota	    }
18084276Syokota	    if (cury > 24) {
18184276Syokota		curx = 0;
18284276Syokota		scroll_up(1, fg_c, bg_c);
18384276Syokota		cury--;
18484276Syokota	    }
18542002Sabial	}
186199855Ssobomax	curs_move(&curx, &cury, curx, cury);
18742002Sabial#endif
18842002Sabial    }
18942002Sabial}
19042002Sabial
19142002Sabial#ifdef TERM_EMU
19242002Sabial
19342002Sabial/* Get cursor position on the screen. Result is in edx. Sets
19442002Sabial * curx and cury appropriately.
19542002Sabial */
19642002Sabialvoid
197199855Ssobomaxget_pos(int *x, int *y)
19842002Sabial{
19984276Syokota
20042002Sabial    v86.ctl = 0;
20142002Sabial    v86.addr = 0x10;
20242002Sabial    v86.eax = 0x0300;
20342002Sabial    v86.ebx = 0x0;
20442002Sabial    v86int();
205199855Ssobomax    *x = v86.edx & 0x00ff;
206199855Ssobomax    *y = (v86.edx & 0xff00) >> 8;
20742002Sabial}
20842002Sabial
20942002Sabial/* Move cursor to x rows and y cols (0-based). */
21042002Sabialvoid
211199855Ssobomaxcurs_move(int *_x, int *_y, int x, int y)
21242002Sabial{
21384276Syokota
21442002Sabial    v86.ctl = 0;
21542002Sabial    v86.addr = 0x10;
21642002Sabial    v86.eax = 0x0200;
21742002Sabial    v86.ebx = 0x0;
21884276Syokota    v86.edx = ((0x00ff & y) << 8) + (0x00ff & x);
21942002Sabial    v86int();
220199855Ssobomax    *_x = x;
221199855Ssobomax    *_y = y;
22242002Sabial    /* If there is ctrl char at this position, cursor would be invisible.
22342002Sabial     * Make it a space instead.
22442002Sabial     */
22584276Syokota    v86.ctl = 0;
22642002Sabial    v86.addr = 0x10;
22742002Sabial    v86.eax = 0x0800;
22884276Syokota    v86.ebx = 0x0;
22942002Sabial    v86int();
23084354Syokota#define isvisible(c)	(((c) >= 32) && ((c) < 255))
23184276Syokota    if (!isvisible(v86.eax & 0x00ff)) {
23284276Syokota	write_char(' ', fg_c, bg_c);
23342002Sabial    }
23442002Sabial}
23542002Sabial
23642002Sabial/* Scroll up the whole window by a number of rows. If rows==0,
23742002Sabial * clear the window. fg and bg are attributes for the new lines
23842002Sabial * inserted in the window.
23942002Sabial */
24042002Sabialvoid
24164187Sjhbscroll_up(int rows, int fgcol, int bgcol)
24242002Sabial{
24384276Syokota
24484276Syokota    if (rows == 0)
24584276Syokota	rows = 25;
24684276Syokota    v86.ctl = 0;
24784276Syokota    v86.addr = 0x10;
24884276Syokota    v86.eax = 0x0600 + (0x00ff & rows);
24984276Syokota    v86.ebx = (bgcol << 12) + (fgcol << 8);
25084276Syokota    v86.ecx = 0x0;
25184276Syokota    v86.edx = 0x184f;
25284276Syokota    v86int();
25342002Sabial}
25442002Sabial
25542002Sabial/* Write character and attribute at cursor position. */
25642002Sabialvoid
25764187Sjhbwrite_char(int c, int fgcol, int bgcol)
25842002Sabial{
25984276Syokota
26084276Syokota    v86.ctl = 0;
26184276Syokota    v86.addr = 0x10;
26284276Syokota    v86.eax = 0x0900 + (0x00ff & c);
26384276Syokota    v86.ebx = (bgcol << 4) + fgcol;
26484276Syokota    v86.ecx = 0x1;
26584276Syokota    v86int();
26642002Sabial}
26742002Sabial
26842002Sabial/**************************************************************/
26942002Sabial/*
27042002Sabial * Screen manipulation functions. They use accumulated data in
27142002Sabial * args[] and argc variables.
27242002Sabial *
27342002Sabial */
27442002Sabial
27542002Sabial/* Clear display from current position to end of screen */
27642002Sabialvoid
27742002SabialCD(void)
27842002Sabial{
27984276Syokota
280199855Ssobomax    get_pos(&curx, &cury);
28184277Syokota    if (curx > 0) {
28284277Syokota	v86.ctl = 0;
28384277Syokota	v86.addr = 0x10;
28484277Syokota	v86.eax = 0x0600;
28584277Syokota	v86.ebx = (bg_c << 4) + fg_c;
28684277Syokota	v86.ecx = (cury << 8) + curx;
28784277Syokota	v86.edx = (cury << 8) + 79;
28884277Syokota	v86int();
28984277Syokota	if (++cury > 24) {
29084277Syokota	    end_term();
29184277Syokota	    return;
29284277Syokota	}
29384277Syokota    }
29442002Sabial    v86.ctl = 0;
29542002Sabial    v86.addr = 0x10;
29642002Sabial    v86.eax = 0x0600;
29784276Syokota    v86.ebx = (bg_c << 4) + fg_c;
29884277Syokota    v86.ecx = (cury << 8) + 0;
29984277Syokota    v86.edx = (24 << 8) + 79;
30042002Sabial    v86int();
30142002Sabial    end_term();
30242002Sabial}
30342002Sabial
30442002Sabial/* Absolute cursor move to args[0] rows and args[1] columns
30542002Sabial * (the coordinates are 1-based).
30642002Sabial */
30742002Sabialvoid
30842002SabialCM(void)
30942002Sabial{
31084276Syokota
31184276Syokota    if (args[0] > 0)
31284276Syokota	args[0]--;
31384276Syokota    if (args[1] > 0)
31484276Syokota	args[1]--;
315199855Ssobomax    curs_move(&curx, &cury, args[1], args[0]);
31642002Sabial    end_term();
31742002Sabial}
31842002Sabial
31942002Sabial/* Home cursor (left top corner) */
32042002Sabialvoid
32142002SabialHO(void)
32242002Sabial{
32384276Syokota
32484276Syokota    argc = 1;
32584276Syokota    args[0] = args[1] = 1;
32684276Syokota    CM();
32742002Sabial}
32842002Sabial
32942002Sabial/* Clear internal state of the terminal emulation code */
33042002Sabialvoid
33142002Sabialend_term(void)
33242002Sabial{
33384276Syokota
33484276Syokota    esc = 0;
33584276Syokota    argc = -1;
33642002Sabial}
33742002Sabial
33842002Sabial/* Gracefully exit ESC-sequence processing in case of misunderstanding */
33942002Sabialvoid
34042002Sabialbail_out(int c)
34142002Sabial{
34284371Syokota    char buf[16], *ch;
34384371Syokota    int i;
34442002Sabial
34584371Syokota    if (esc) {
34684276Syokota	vidc_rawputchar('\033');
34784371Syokota	if (esc != '\033')
34884371Syokota	    vidc_rawputchar(esc);
34984371Syokota	for (i = 0; i <= argc; ++i) {
35084371Syokota	    sprintf(buf, "%d", args[i]);
35184276Syokota	    ch = buf;
35284276Syokota	    while (*ch)
35384276Syokota		vidc_rawputchar(*ch++);
35442002Sabial	}
35584276Syokota    }
35684276Syokota    vidc_rawputchar(c);
35784276Syokota    end_term();
35842002Sabial}
35942002Sabial
36084371Syokotastatic void
361144837Sstefanfget_arg(int c)
36284371Syokota{
36384371Syokota
36484371Syokota    if (argc < 0)
36584371Syokota	argc = 0;
36684371Syokota    args[argc] *= 10;
36784371Syokota    args[argc] += c - '0';
36884371Syokota}
36984371Syokota
37042002Sabial/* Emulate basic capabilities of cons25 terminal */
37142002Sabialvoid
37242002Sabialvidc_term_emu(int c)
37342002Sabial{
37484371Syokota    static int ansi_col[] = {
37584371Syokota	0, 4, 2, 6, 1, 5, 3, 7,
37684371Syokota    };
37784371Syokota    int t;
37884371Syokota    int i;
37942002Sabial
38084371Syokota    switch (esc) {
38184371Syokota    case 0:
38284371Syokota	switch (c) {
38384371Syokota	case '\033':
38484371Syokota	    esc = c;
38584371Syokota	    break;
38684371Syokota	default:
38742002Sabial	    vidc_rawputchar(c);
38884371Syokota	    break;
38942002Sabial	}
39084371Syokota	break;
39142002Sabial
39242002Sabial    case '\033':
39384371Syokota	switch (c) {
39484371Syokota	case '[':
39584371Syokota	    esc = c;
39684371Syokota	    args[0] = 0;
39784371Syokota	    argc = -1;
39884371Syokota	    break;
39984371Syokota	default:
40084371Syokota	    bail_out(c);
40184371Syokota	    break;
40284371Syokota	}
40342002Sabial	break;
40484371Syokota
40542002Sabial    case '[':
40684371Syokota	switch (c) {
40784371Syokota	case ';':
40884371Syokota	    if (argc < 0)	/* XXX */
40984371Syokota		argc = 0;
41084371Syokota	    else if (argc + 1 >= MAXARGS)
41184371Syokota		bail_out(c);
41284371Syokota	    else
41384371Syokota		args[++argc] = 0;
41484371Syokota	    break;
41584371Syokota	case 'H':
41684371Syokota	    if (argc < 0)
41742002Sabial		HO();
41884371Syokota	    else if (argc == 1)
41942002Sabial		CM();
42084371Syokota	    else
42142002Sabial		bail_out(c);
42284371Syokota	    break;
42384371Syokota	case 'J':
42484371Syokota	    if (argc < 0)
42584371Syokota		CD();
42684371Syokota	    else
42784371Syokota		bail_out(c);
42884371Syokota	    break;
42984371Syokota	case 'm':
43084371Syokota	    if (argc < 0) {
43184371Syokota		fg_c = DEFAULT_FGCOLOR;
43284371Syokota		bg_c = DEFAULT_BGCOLOR;
43342002Sabial	    }
43484371Syokota	    for (i = 0; i <= argc; ++i) {
43584371Syokota		switch (args[i]) {
43684371Syokota		case 0:		/* back to normal */
43784371Syokota		    fg_c = DEFAULT_FGCOLOR;
43884371Syokota		    bg_c = DEFAULT_BGCOLOR;
43984371Syokota		    break;
44084371Syokota		case 1:		/* bold */
44184371Syokota		    fg_c |= 0x8;
44284371Syokota		    break;
44384371Syokota		case 4:		/* underline */
44484371Syokota		case 5:		/* blink */
44584371Syokota		    bg_c |= 0x8;
44684371Syokota		    break;
44784371Syokota		case 7:		/* reverse */
44884371Syokota		    t = fg_c;
44984371Syokota		    fg_c = bg_c;
45084371Syokota		    bg_c = t;
45184371Syokota		    break;
45284371Syokota		case 30: case 31: case 32: case 33:
45384371Syokota		case 34: case 35: case 36: case 37:
45484371Syokota		    fg_c = ansi_col[args[i] - 30];
45584371Syokota		    break;
45684371Syokota		case 39:	/* normal */
45784371Syokota		    fg_c = DEFAULT_FGCOLOR;
45884371Syokota		    break;
45984371Syokota		case 40: case 41: case 42: case 43:
46084371Syokota		case 44: case 45: case 46: case 47:
46184371Syokota		    bg_c = ansi_col[args[i] - 40];
46284371Syokota		    break;
46384371Syokota		case 49:	/* normal */
46484371Syokota		    bg_c = DEFAULT_BGCOLOR;
46584371Syokota		    break;
46684371Syokota		}
46784371Syokota	    }
46884371Syokota	    end_term();
46984371Syokota	    break;
47084371Syokota	default:
47184371Syokota	    if (isdigit(c))
47284371Syokota		get_arg(c);
47384371Syokota	    else
47442002Sabial		bail_out(c);
47584371Syokota	    break;
47684371Syokota	}
47742002Sabial	break;
47884371Syokota
47942002Sabial    default:
48084371Syokota	bail_out(c);
48142002Sabial	break;
48242002Sabial    }
48339441Smsmith}
48442002Sabial#endif
48539441Smsmith
48642002Sabialstatic void
48742002Sabialvidc_putchar(int c)
48842002Sabial{
48942002Sabial#ifdef TERM_EMU
49042002Sabial    vidc_term_emu(c);
49142002Sabial#else
49242002Sabial    vidc_rawputchar(c);
49342002Sabial#endif
49442002Sabial}
49542002Sabial
49638465Smsmithstatic int
49739441Smsmithvidc_getchar(void)
49838465Smsmith{
49984276Syokota
50039441Smsmith    if (vidc_ischar()) {
50139441Smsmith	v86.ctl = 0;
50239441Smsmith	v86.addr = 0x16;
50339441Smsmith	v86.eax = 0x0;
50439441Smsmith	v86int();
50584276Syokota	return (v86.eax & 0xff);
50638465Smsmith    } else {
50784276Syokota	return (-1);
50838465Smsmith    }
50938465Smsmith}
51038465Smsmith
51139441Smsmithstatic int
51239441Smsmithvidc_ischar(void)
51339441Smsmith{
51484276Syokota
51540032Smsmith    v86.ctl = V86_FLAGS;
51639441Smsmith    v86.addr = 0x16;
51739441Smsmith    v86.eax = 0x100;
51839441Smsmith    v86int();
519226746Sjhb    return (!V86_ZR(v86.efl));
52039441Smsmith}
52139441Smsmith
52239441Smsmith#if KEYBOARD_PROBE
52339441Smsmith
52438465Smsmith#define PROBE_MAXRETRY	5
52538465Smsmith#define PROBE_MAXWAIT	400
52638465Smsmith#define IO_DUMMY	0x84
52738465Smsmith#define IO_KBD		0x060		/* 8042 Keyboard */
52838465Smsmith
52938465Smsmith/* selected defines from kbdio.h */
53038465Smsmith#define KBD_STATUS_PORT 	4	/* status port, read */
53138465Smsmith#define KBD_DATA_PORT		0	/* data port, read/write
53238465Smsmith					 * also used as keyboard command
53338465Smsmith					 * and mouse command port
53438465Smsmith					 */
53538465Smsmith#define KBDC_ECHO		0x00ee
53638465Smsmith#define KBDS_ANY_BUFFER_FULL	0x0001
53738465Smsmith#define KBDS_INPUT_BUFFER_FULL	0x0002
53838465Smsmith#define KBD_ECHO		0x00ee
53938465Smsmith
54038465Smsmith/* 7 microsec delay necessary for some keyboard controllers */
54138465Smsmithstatic void
54238465Smsmithdelay7(void)
54338465Smsmith{
54438465Smsmith    /*
54542002Sabial     * I know this is broken, but no timer is available yet at this stage...
54638465Smsmith     * See also comments in `delay1ms()'.
54738465Smsmith     */
54838465Smsmith    inb(IO_DUMMY); inb(IO_DUMMY);
54938465Smsmith    inb(IO_DUMMY); inb(IO_DUMMY);
55038465Smsmith    inb(IO_DUMMY); inb(IO_DUMMY);
55138465Smsmith}
55238465Smsmith
55338465Smsmith/*
55438465Smsmith * This routine uses an inb to an unused port, the time to execute that
55538465Smsmith * inb is approximately 1.25uS.  This value is pretty constant across
55638465Smsmith * all CPU's and all buses, with the exception of some PCI implentations
55780203Skris * that do not forward this I/O address to the ISA bus as they know it
55838465Smsmith * is not a valid ISA bus address, those machines execute this inb in
55938465Smsmith * 60 nS :-(.
56038465Smsmith *
56138465Smsmith */
56238465Smsmithstatic void
56338465Smsmithdelay1ms(void)
56438465Smsmith{
56538465Smsmith    int i = 800;
56638465Smsmith    while (--i >= 0)
56738465Smsmith	(void)inb(0x84);
56838465Smsmith}
56938465Smsmith
57038465Smsmith/*
57138465Smsmith * We use the presence/absence of a keyboard to determine whether the internal
57238465Smsmith * console can be used for input.
57338465Smsmith *
57438465Smsmith * Perform a simple test on the keyboard; issue the ECHO command and see
57538465Smsmith * if the right answer is returned. We don't do anything as drastic as
57638465Smsmith * full keyboard reset; it will be too troublesome and take too much time.
57738465Smsmith */
57838465Smsmithstatic int
57938465Smsmithprobe_keyboard(void)
58038465Smsmith{
58138465Smsmith    int retry = PROBE_MAXRETRY;
58238465Smsmith    int wait;
58338465Smsmith    int i;
58438465Smsmith
58538465Smsmith    while (--retry >= 0) {
58638465Smsmith	/* flush any noise */
58738465Smsmith	while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
58838465Smsmith	    delay7();
58938465Smsmith	    inb(IO_KBD + KBD_DATA_PORT);
59038465Smsmith	    delay1ms();
59138465Smsmith	}
59238465Smsmith
59338465Smsmith	/* wait until the controller can accept a command */
59438465Smsmith	for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
59538465Smsmith	    if (((i = inb(IO_KBD + KBD_STATUS_PORT))
59638465Smsmith                & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
59738465Smsmith		break;
59838465Smsmith	    if (i & KBDS_ANY_BUFFER_FULL) {
59938465Smsmith		delay7();
60038465Smsmith	        inb(IO_KBD + KBD_DATA_PORT);
60138465Smsmith	    }
60238465Smsmith	    delay1ms();
60338465Smsmith	}
60438465Smsmith	if (wait <= 0)
60538465Smsmith	    continue;
60638465Smsmith
60738465Smsmith	/* send the ECHO command */
60838465Smsmith	outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
60938465Smsmith
61038465Smsmith	/* wait for a response */
61138465Smsmith	for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
61238465Smsmith	     if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
61338465Smsmith		 break;
61438465Smsmith	     delay1ms();
61538465Smsmith	}
61638465Smsmith	if (wait <= 0)
61738465Smsmith	    continue;
61838465Smsmith
61938465Smsmith	delay7();
62038465Smsmith	i = inb(IO_KBD + KBD_DATA_PORT);
62138465Smsmith#ifdef PROBE_KBD_BEBUG
62238465Smsmith        printf("probe_keyboard: got 0x%x.\n", i);
62338465Smsmith#endif
62438465Smsmith	if (i == KBD_ECHO) {
62538465Smsmith	    /* got the right answer */
626232309Sjkim	    return (1);
62738465Smsmith	}
62838465Smsmith    }
62938465Smsmith
630232309Sjkim    return (0);
63138465Smsmith}
63239441Smsmith#endif /* KEYBOARD_PROBE */
633