19890ff8Toomas Soome/*
2199767fToomas Soome * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
3199767fToomas Soome * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
4199767fToomas Soome * All rights reserved.
5199767fToomas Soome *
6199767fToomas Soome * Redistribution and use in source and binary forms, with or without
7199767fToomas Soome * modification, are permitted provided that the following conditions
8199767fToomas Soome * are met:
9199767fToomas Soome * 1. Redistributions of source code must retain the above copyright
10199767fToomas Soome *    notice, this list of conditions and the following disclaimer.
11199767fToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
12199767fToomas Soome *    notice, this list of conditions and the following disclaimer in the
13199767fToomas Soome *    documentation and/or other materials provided with the distribution.
14199767fToomas Soome *
15199767fToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16199767fToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17199767fToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18199767fToomas Soome * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19199767fToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20199767fToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21199767fToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22199767fToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23199767fToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24199767fToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25199767fToomas Soome * SUCH DAMAGE.
26199767fToomas Soome *
279890ff8Toomas Soome *	Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
28199767fToomas Soome */
29199767fToomas Soome
30199767fToomas Soome#include <sys/cdefs.h>
31199767fToomas Soome
32199767fToomas Soome#include <stand.h>
33199767fToomas Soome#include <bootstrap.h>
349890ff8Toomas Soome#include <sys/tem_impl.h>
359890ff8Toomas Soome#include <sys/visual_io.h>
369890ff8Toomas Soome#include <sys/multiboot2.h>
37199767fToomas Soome#include <btxv86.h>
38199767fToomas Soome#include <machine/psl.h>
399890ff8Toomas Soome#include <machine/metadata.h>
40199767fToomas Soome#include "libi386.h"
419890ff8Toomas Soome#include "vbe.h"
429890ff8Toomas Soome#include <gfx_fb.h>
437bc07caToomas Soome#include <rbx.h>
449890ff8Toomas Soome#include <sys/vgareg.h>
459890ff8Toomas Soome#include <sys/vgasubr.h>
469890ff8Toomas Soome#include <machine/cpufunc.h>
47199767fToomas Soome
48199767fToomas Soome#if KEYBOARD_PROBE
49199767fToomas Soome
50199767fToomas Soomestatic int	probe_keyboard(void);
51199767fToomas Soome#endif
52199767fToomas Soomestatic void	vidc_probe(struct console *cp);
53199767fToomas Soomestatic int	vidc_init(struct console *cp, int arg);
54199767fToomas Soomestatic void	vidc_putchar(struct console *cp, int c);
55199767fToomas Soomestatic int	vidc_getchar(struct console *cp);
56199767fToomas Soomestatic int	vidc_ischar(struct console *cp);
579890ff8Toomas Soomestatic int	vidc_ioctl(struct console *cp, int cmd, void *data);
589890ff8Toomas Soomestatic void	vidc_biosputchar(int c);
5980e4791Toomas Soomestatic void	vidc_devinfo(struct console *cp);
609890ff8Toomas Soome
619890ff8Toomas Soomestatic int vidc_vbe_devinit(struct vis_devinit *);
629890ff8Toomas Soomestatic void vidc_cons_cursor(struct vis_conscursor *);
639890ff8Toomas Soomestatic int vidc_vbe_cons_put_cmap(struct vis_cmap *);
649890ff8Toomas Soome
659890ff8Toomas Soomestatic int vidc_text_devinit(struct vis_devinit *);
669890ff8Toomas Soomestatic int vidc_text_cons_clear(struct vis_consclear *);
679890ff8Toomas Soomestatic void vidc_text_cons_copy(struct vis_conscopy *);
689890ff8Toomas Soomestatic void vidc_text_cons_display(struct vis_consdisplay *);
699890ff8Toomas Soomestatic void vidc_text_set_cursor(screen_pos_t, screen_pos_t, boolean_t);
709890ff8Toomas Soomestatic void vidc_text_get_cursor(screen_pos_t *, screen_pos_t *);
719890ff8Toomas Soomestatic int vidc_text_cons_put_cmap(struct vis_cmap *);
729890ff8Toomas Soome
739890ff8Toomas Soomestatic int vidc_started;
749890ff8Toomas Soomestatic uint16_t	*vgatext;
75199767fToomas Soome
769890ff8Toomas Soome/* mode change callback and argument from tem */
779890ff8Toomas Soomestatic vis_modechg_cb_t modechg_cb;
789890ff8Toomas Soomestatic struct vis_modechg_arg *modechg_arg;
799890ff8Toomas Soomestatic tem_vt_state_t tem;
80199767fToomas Soome
81199767fToomas Soome#define	KEYBUFSZ	10
82c7832f2Toomas Soome#define	DEFAULT_FGCOLOR	7
83c7832f2Toomas Soome#define	DEFAULT_BGCOLOR	0
84199767fToomas Soome
859890ff8Toomas Soomestatic uint8_t	keybuf[KEYBUFSZ];	/* keybuf for extended codes */
86199767fToomas Soome
87199767fToomas Soomestruct console text = {
889890ff8Toomas Soome	.c_name = "text",
899890ff8Toomas Soome	.c_desc = "internal video/keyboard",
909890ff8Toomas Soome	.c_flags = 0,
919890ff8Toomas Soome	.c_probe = vidc_probe,
929890ff8Toomas Soome	.c_init = vidc_init,
939890ff8Toomas Soome	.c_out = vidc_putchar,
949890ff8Toomas Soome	.c_in = vidc_getchar,
959890ff8Toomas Soome	.c_ready = vidc_ischar,
969890ff8Toomas Soome	.c_ioctl = vidc_ioctl,
9780e4791Toomas Soome	.c_devinfo = vidc_devinfo,
989890ff8Toomas Soome	.c_private = NULL
99199767fToomas Soome};
100199767fToomas Soome
1019890ff8Toomas Soomestatic struct vis_identifier fb_ident = { "vidc_fb" };
1029890ff8Toomas Soomestatic struct vis_identifier text_ident = { "vidc_text" };
1039890ff8Toomas Soome
1049890ff8Toomas Soomestruct visual_ops fb_ops = {
1059890ff8Toomas Soome	.ident = &fb_ident,
1069890ff8Toomas Soome	.kdsetmode = NULL,
1079890ff8Toomas Soome	.devinit = vidc_vbe_devinit,
1089890ff8Toomas Soome	.cons_copy = NULL,
1099890ff8Toomas Soome	.cons_display = NULL,
1109890ff8Toomas Soome	.cons_cursor = vidc_cons_cursor,
1119890ff8Toomas Soome	.cons_clear = NULL,
1129890ff8Toomas Soome	.cons_put_cmap = vidc_vbe_cons_put_cmap
1139890ff8Toomas Soome};
114199767fToomas Soome
1159890ff8Toomas Soomestruct visual_ops text_ops = {
1169890ff8Toomas Soome	.ident = &text_ident,
1179890ff8Toomas Soome	.kdsetmode = NULL,
1189890ff8Toomas Soome	.devinit = vidc_text_devinit,
1199890ff8Toomas Soome	.cons_copy = vidc_text_cons_copy,
1209890ff8Toomas Soome	.cons_display = vidc_text_cons_display,
1219890ff8Toomas Soome	.cons_cursor = vidc_cons_cursor,
1229890ff8Toomas Soome	.cons_clear = vidc_text_cons_clear,
1239890ff8Toomas Soome	.cons_put_cmap = vidc_text_cons_put_cmap
1249890ff8Toomas Soome};
125199767fToomas Soome
1269890ff8Toomas Soome/*
1279890ff8Toomas Soome * platform specific functions for tem
1289890ff8Toomas Soome */
1299890ff8Toomas Soomeint
1309890ff8Toomas Soomeplat_stdout_is_framebuffer(void)
131199767fToomas Soome{
1329890ff8Toomas Soome	if (vbe_available() && VBE_VALID_MODE(vbe_get_mode())) {
1339890ff8Toomas Soome		return (1);
1349890ff8Toomas Soome	}
135c7832f2Toomas Soome	return (0);
136199767fToomas Soome}
137199767fToomas Soome
138199767fToomas Soomevoid
1399890ff8Toomas Soomeplat_tem_hide_prom_cursor(void)
140199767fToomas Soome{
1419890ff8Toomas Soome	vidc_text_set_cursor(0, 0, B_FALSE);
142199767fToomas Soome}
143199767fToomas Soome
1449890ff8Toomas Soomevoid
1459890ff8Toomas Soomeplat_tem_get_prom_pos(uint32_t *row, uint32_t *col)
146199767fToomas Soome{
1479890ff8Toomas Soome	screen_pos_t x, y;
1489890ff8Toomas Soome
1499890ff8Toomas Soome	if (plat_stdout_is_framebuffer()) {
1509890ff8Toomas Soome		*row = 0;
1519890ff8Toomas Soome		*col = 0;
1529890ff8Toomas Soome	} else {
1539890ff8Toomas Soome		vidc_text_get_cursor(&y, &x);
154c7832f2Toomas Soome		*row = (uint32_t)y;
155c7832f2Toomas Soome		*col = (uint32_t)x;
156199767fToomas Soome	}
157199767fToomas Soome}
158199767fToomas Soome
1599890ff8Toomas Soome/*
1609890ff8Toomas Soome * plat_tem_get_prom_size() is supposed to return screen size
1619890ff8Toomas Soome * in chars. Return real data for text mode and TEM defaults for graphical
1629890ff8Toomas Soome * mode, so the tem can compute values based on default and font.
163199767fToomas Soome */
164199767fToomas Soomevoid
1659890ff8Toomas Soomeplat_tem_get_prom_size(size_t *height, size_t *width)
166199767fToomas Soome{
1679890ff8Toomas Soome	if (plat_stdout_is_framebuffer()) {
1689890ff8Toomas Soome		*height = TEM_DEFAULT_ROWS;
1699890ff8Toomas Soome		*width = TEM_DEFAULT_COLS;
1709890ff8Toomas Soome	} else {
1719890ff8Toomas Soome		*height = TEXT_ROWS;
1729890ff8Toomas Soome		*width = TEXT_COLS;
1739890ff8Toomas Soome	}
174199767fToomas Soome}
175199767fToomas Soome
176199767fToomas Soomevoid
1779890ff8Toomas Soomeplat_cons_update_mode(int mode __unused)
178199767fToomas Soome{
1799890ff8Toomas Soome	struct vis_devinit devinit;
1809890ff8Toomas Soome
1819890ff8Toomas Soome	if (tem == NULL)	/* tem is not set up */
1829890ff8Toomas Soome		return;
1839890ff8Toomas Soome
1849890ff8Toomas Soome	if (plat_stdout_is_framebuffer()) {
1859890ff8Toomas Soome		devinit.version = VIS_CONS_REV;
1869890ff8Toomas Soome		devinit.width = gfx_fb.framebuffer_common.framebuffer_width;
1879890ff8Toomas Soome		devinit.height = gfx_fb.framebuffer_common.framebuffer_height;
1889890ff8Toomas Soome		devinit.depth = gfx_fb.framebuffer_common.framebuffer_bpp;
1899890ff8Toomas Soome		devinit.linebytes = gfx_fb.framebuffer_common.framebuffer_pitch;
1909890ff8Toomas Soome		devinit.color_map = gfx_fb_color_map;
1919890ff8Toomas Soome		devinit.mode = VIS_PIXEL;
1929890ff8Toomas Soome		text.c_private = &fb_ops;
1939890ff8Toomas Soome	} else {
1949890ff8Toomas Soome		devinit.version = VIS_CONS_REV;
1959890ff8Toomas Soome		devinit.width = TEXT_COLS;
1969890ff8Toomas Soome		devinit.height = TEXT_ROWS;
1979890ff8Toomas Soome		devinit.depth = 4;
1989890ff8Toomas Soome		devinit.linebytes = TEXT_COLS;
1999890ff8Toomas Soome		devinit.color_map = NULL;
2009890ff8Toomas Soome		devinit.mode = VIS_TEXT;
2019890ff8Toomas Soome		text.c_private = &text_ops;
2029890ff8Toomas Soome	}
203199767fToomas Soome
2049890ff8Toomas Soome	modechg_cb(modechg_arg, &devinit);
205199767fToomas Soome}
206199767fToomas Soome
2079890ff8Toomas Soomestatic int
2089890ff8Toomas Soomevidc_vbe_devinit(struct vis_devinit *devinit)
209199767fToomas Soome{
2109890ff8Toomas Soome	if (plat_stdout_is_framebuffer() == 0)
2119890ff8Toomas Soome		return (1);
2129890ff8Toomas Soome
2139890ff8Toomas Soome	devinit->version = VIS_CONS_REV;
2149890ff8Toomas Soome	devinit->width = gfx_fb.framebuffer_common.framebuffer_width;
2159890ff8Toomas Soome	devinit->height = gfx_fb.framebuffer_common.framebuffer_height;
2169890ff8Toomas Soome	devinit->depth = gfx_fb.framebuffer_common.framebuffer_bpp;
2179890ff8Toomas Soome	devinit->linebytes = gfx_fb.framebuffer_common.framebuffer_pitch;
2189890ff8Toomas Soome	devinit->color_map = gfx_fb_color_map;
2199890ff8Toomas Soome	devinit->mode = VIS_PIXEL;
2209890ff8Toomas Soome
2219890ff8Toomas Soome	modechg_cb = devinit->modechg_cb;
2229890ff8Toomas Soome	modechg_arg = devinit->modechg_arg;
2239890ff8Toomas Soome
2249890ff8Toomas Soome	return (0);
225199767fToomas Soome}
226199767fToomas Soome
2279890ff8Toomas Soomestatic int
2289890ff8Toomas Soomevidc_text_devinit(struct vis_devinit *devinit)
229199767fToomas Soome{
2309890ff8Toomas Soome	if (plat_stdout_is_framebuffer())
2319890ff8Toomas Soome		return (1);
232199767fToomas Soome
2339890ff8Toomas Soome	devinit->version = VIS_CONS_REV;
2349890ff8Toomas Soome	devinit->width = TEXT_COLS;
2359890ff8Toomas Soome	devinit->height = TEXT_ROWS;
2369890ff8Toomas Soome	devinit->depth = 4;
2379890ff8Toomas Soome	devinit->linebytes = TEXT_COLS;
2389890ff8Toomas Soome	devinit->color_map = NULL;
2399890ff8Toomas Soome	devinit->mode = VIS_TEXT;
240199767fToomas Soome
2419890ff8Toomas Soome	modechg_cb = devinit->modechg_cb;
2429890ff8Toomas Soome	modechg_arg = devinit->modechg_arg;
243199767fToomas Soome
2449890ff8Toomas Soome	return (0);
245199767fToomas Soome}
246199767fToomas Soome
2479890ff8Toomas Soomestatic int
2489890ff8Toomas Soomevidc_text_cons_clear(struct vis_consclear *ca)
249199767fToomas Soome{
2509890ff8Toomas Soome	uint16_t val;
2519890ff8Toomas Soome	int i;
252199767fToomas Soome
2539890ff8Toomas Soome	val = (solaris_color_to_pc_color[ca->bg_color & 0xf] << 4) |
2549890ff8Toomas Soome	    DEFAULT_FGCOLOR;
2559890ff8Toomas Soome	val = (val << 8) | ' ';
2569890ff8Toomas Soome
2579890ff8Toomas Soome	for (i = 0; i < TEXT_ROWS * TEXT_COLS; i++)
2589890ff8Toomas Soome		vgatext[i] = val;
2599890ff8Toomas Soome
2609890ff8Toomas Soome	return (0);
2619890ff8Toomas Soome}
2629890ff8Toomas Soome
2639890ff8Toomas Soomestatic void
2649890ff8Toomas Soomevidc_text_cons_copy(struct vis_conscopy *ma)
2659890ff8Toomas Soome{
2669890ff8Toomas Soome	uint16_t  *from;
2679890ff8Toomas Soome	uint16_t *to;
2689890ff8Toomas Soome	int cnt;
2699890ff8Toomas Soome	screen_size_t chars_per_row;
2709890ff8Toomas Soome	uint16_t *to_row_start;
2719890ff8Toomas Soome	uint16_t *from_row_start;
2729890ff8Toomas Soome	screen_size_t rows_to_move;
2739890ff8Toomas Soome	uint16_t *base;
2749890ff8Toomas Soome
2759890ff8Toomas Soome	/*
2769890ff8Toomas Soome	 * Sanity checks.  Note that this is a last-ditch effort to avoid
2779890ff8Toomas Soome	 * damage caused by broken-ness or maliciousness above.
2789890ff8Toomas Soome	 */
2799890ff8Toomas Soome	if (ma->s_col < 0 || ma->s_col >= TEXT_COLS ||
2809890ff8Toomas Soome	    ma->s_row < 0 || ma->s_row >= TEXT_ROWS ||
2819890ff8Toomas Soome	    ma->e_col < 0 || ma->e_col >= TEXT_COLS ||
2829890ff8Toomas Soome	    ma->e_row < 0 || ma->e_row >= TEXT_ROWS ||
2839890ff8Toomas Soome	    ma->t_col < 0 || ma->t_col >= TEXT_COLS ||
2849890ff8Toomas Soome	    ma->t_row < 0 || ma->t_row >= TEXT_ROWS ||
2859890ff8Toomas Soome	    ma->s_col > ma->e_col ||
2869890ff8Toomas Soome	    ma->s_row > ma->e_row)
2879890ff8Toomas Soome		return;
2889890ff8Toomas Soome
2899890ff8Toomas Soome	/*
2909890ff8Toomas Soome	 * Remember we're going to copy shorts because each
2919890ff8Toomas Soome	 * character/attribute pair is 16 bits.
2929890ff8Toomas Soome	 */
2939890ff8Toomas Soome	chars_per_row = ma->e_col - ma->s_col + 1;
2949890ff8Toomas Soome	rows_to_move = ma->e_row - ma->s_row + 1;
2959890ff8Toomas Soome
2969890ff8Toomas Soome	/* More sanity checks. */
2979890ff8Toomas Soome	if (ma->t_row + rows_to_move > TEXT_ROWS ||
2989890ff8Toomas Soome	    ma->t_col + chars_per_row > TEXT_COLS)
2999890ff8Toomas Soome		return;
3009890ff8Toomas Soome
3019890ff8Toomas Soome	base = vgatext;
3029890ff8Toomas Soome
3039890ff8Toomas Soome	to_row_start = base + ((ma->t_row * TEXT_COLS) + ma->t_col);
3049890ff8Toomas Soome	from_row_start = base + ((ma->s_row * TEXT_COLS) + ma->s_col);
3059890ff8Toomas Soome
3069890ff8Toomas Soome	if (to_row_start < from_row_start) {
3079890ff8Toomas Soome		while (rows_to_move-- > 0) {
3089890ff8Toomas Soome			to = to_row_start;
3099890ff8Toomas Soome			from = from_row_start;
3109890ff8Toomas Soome			to_row_start += TEXT_COLS;
3119890ff8Toomas Soome			from_row_start += TEXT_COLS;
3129890ff8Toomas Soome			for (cnt = chars_per_row; cnt-- > 0; )
3139890ff8Toomas Soome				*to++ = *from++;
3149890ff8Toomas Soome		}
3159890ff8Toomas Soome	} else {
3169890ff8Toomas Soome		/*
3179890ff8Toomas Soome		 * Offset to the end of the region and copy backwards.
3189890ff8Toomas Soome		 */
3199890ff8Toomas Soome		cnt = rows_to_move * TEXT_COLS + chars_per_row;
3209890ff8Toomas Soome		to_row_start += cnt;
3219890ff8Toomas Soome		from_row_start += cnt;
3229890ff8Toomas Soome
3239890ff8Toomas Soome		while (rows_to_move-- > 0) {
3249890ff8Toomas Soome			to_row_start -= TEXT_COLS;
3259890ff8Toomas Soome			from_row_start -= TEXT_COLS;
3269890ff8Toomas Soome			to = to_row_start;
3279890ff8Toomas Soome			from = from_row_start;
3289890ff8Toomas Soome			for (cnt = chars_per_row; cnt-- > 0; )
3299890ff8Toomas Soome				*--to = *--from;
3309890ff8Toomas Soome		}
331199767fToomas Soome	}
332199767fToomas Soome}
333199767fToomas Soome
3349890ff8Toomas Soome/*
3359890ff8Toomas Soome * Binary searchable table for Unicode to CP437 conversion.
336199767fToomas Soome */
3379890ff8Toomas Soomestruct unicp437 {
3389890ff8Toomas Soome	uint16_t	unicode_base;
3399890ff8Toomas Soome	uint8_t		cp437_base;
3409890ff8Toomas Soome	uint8_t		length;
3419890ff8Toomas Soome};
342199767fToomas Soome
3439890ff8Toomas Soomestatic const struct unicp437 cp437table[] = {
3449890ff8Toomas Soome	{ 0x0020, 0x20, 0x5e }, { 0x00a0, 0x20, 0x00 },
3459890ff8Toomas Soome	{ 0x00a1, 0xad, 0x00 }, { 0x00a2, 0x9b, 0x00 },
3469890ff8Toomas Soome	{ 0x00a3, 0x9c, 0x00 }, { 0x00a5, 0x9d, 0x00 },
3479890ff8Toomas Soome	{ 0x00a7, 0x15, 0x00 }, { 0x00aa, 0xa6, 0x00 },
3489890ff8Toomas Soome	{ 0x00ab, 0xae, 0x00 }, { 0x00ac, 0xaa, 0x00 },
3499890ff8Toomas Soome	{ 0x00b0, 0xf8, 0x00 }, { 0x00b1, 0xf1, 0x00 },
3509890ff8Toomas Soome	{ 0x00b2, 0xfd, 0x00 }, { 0x00b5, 0xe6, 0x00 },
3519890ff8Toomas Soome	{ 0x00b6, 0x14, 0x00 }, { 0x00b7, 0xfa, 0x00 },
3529890ff8Toomas Soome	{ 0x00ba, 0xa7, 0x00 }, { 0x00bb, 0xaf, 0x00 },
3539890ff8Toomas Soome	{ 0x00bc, 0xac, 0x00 }, { 0x00bd, 0xab, 0x00 },
3549890ff8Toomas Soome	{ 0x00bf, 0xa8, 0x00 }, { 0x00c4, 0x8e, 0x01 },
3559890ff8Toomas Soome	{ 0x00c6, 0x92, 0x00 }, { 0x00c7, 0x80, 0x00 },
3569890ff8Toomas Soome	{ 0x00c9, 0x90, 0x00 }, { 0x00d1, 0xa5, 0x00 },
3579890ff8Toomas Soome	{ 0x00d6, 0x99, 0x00 }, { 0x00dc, 0x9a, 0x00 },
3589890ff8Toomas Soome	{ 0x00df, 0xe1, 0x00 }, { 0x00e0, 0x85, 0x00 },
3599890ff8Toomas Soome	{ 0x00e1, 0xa0, 0x00 }, { 0x00e2, 0x83, 0x00 },
3609890ff8Toomas Soome	{ 0x00e4, 0x84, 0x00 }, { 0x00e5, 0x86, 0x00 },
3619890ff8Toomas Soome	{ 0x00e6, 0x91, 0x00 }, { 0x00e7, 0x87, 0x00 },
3629890ff8Toomas Soome	{ 0x00e8, 0x8a, 0x00 }, { 0x00e9, 0x82, 0x00 },
3639890ff8Toomas Soome	{ 0x00ea, 0x88, 0x01 }, { 0x00ec, 0x8d, 0x00 },
3649890ff8Toomas Soome	{ 0x00ed, 0xa1, 0x00 }, { 0x00ee, 0x8c, 0x00 },
3659890ff8Toomas Soome	{ 0x00ef, 0x8b, 0x00 }, { 0x00f0, 0xeb, 0x00 },
3669890ff8Toomas Soome	{ 0x00f1, 0xa4, 0x00 }, { 0x00f2, 0x95, 0x00 },
3679890ff8Toomas Soome	{ 0x00f3, 0xa2, 0x00 }, { 0x00f4, 0x93, 0x00 },
3689890ff8Toomas Soome	{ 0x00f6, 0x94, 0x00 }, { 0x00f7, 0xf6, 0x00 },
3699890ff8Toomas Soome	{ 0x00f8, 0xed, 0x00 }, { 0x00f9, 0x97, 0x00 },
3709890ff8Toomas Soome	{ 0x00fa, 0xa3, 0x00 }, { 0x00fb, 0x96, 0x00 },
3719890ff8Toomas Soome	{ 0x00fc, 0x81, 0x00 }, { 0x00ff, 0x98, 0x00 },
3729890ff8Toomas Soome	{ 0x0192, 0x9f, 0x00 }, { 0x0393, 0xe2, 0x00 },
3739890ff8Toomas Soome	{ 0x0398, 0xe9, 0x00 }, { 0x03a3, 0xe4, 0x00 },
3749890ff8Toomas Soome	{ 0x03a6, 0xe8, 0x00 }, { 0x03a9, 0xea, 0x00 },
3759890ff8Toomas Soome	{ 0x03b1, 0xe0, 0x01 }, { 0x03b4, 0xeb, 0x00 },
3769890ff8Toomas Soome	{ 0x03b5, 0xee, 0x00 }, { 0x03bc, 0xe6, 0x00 },
3779890ff8Toomas Soome	{ 0x03c0, 0xe3, 0x00 }, { 0x03c3, 0xe5, 0x00 },
3789890ff8Toomas Soome	{ 0x03c4, 0xe7, 0x00 }, { 0x03c6, 0xed, 0x00 },
3799890ff8Toomas Soome	{ 0x03d5, 0xed, 0x00 }, { 0x2010, 0x2d, 0x00 },
3809890ff8Toomas Soome	{ 0x2014, 0x2d, 0x00 }, { 0x2018, 0x60, 0x00 },
3819890ff8Toomas Soome	{ 0x2019, 0x27, 0x00 }, { 0x201c, 0x22, 0x00 },
3829890ff8Toomas Soome	{ 0x201d, 0x22, 0x00 }, { 0x2022, 0x07, 0x00 },
3839890ff8Toomas Soome	{ 0x203c, 0x13, 0x00 }, { 0x207f, 0xfc, 0x00 },
3849890ff8Toomas Soome	{ 0x20a7, 0x9e, 0x00 }, { 0x20ac, 0xee, 0x00 },
3859890ff8Toomas Soome	{ 0x2126, 0xea, 0x00 }, { 0x2190, 0x1b, 0x00 },
3869890ff8Toomas Soome	{ 0x2191, 0x18, 0x00 }, { 0x2192, 0x1a, 0x00 },
3879890ff8Toomas Soome	{ 0x2193, 0x19, 0x00 }, { 0x2194, 0x1d, 0x00 },
3889890ff8Toomas Soome	{ 0x2195, 0x12, 0x00 }, { 0x21a8, 0x17, 0x00 },
3899890ff8Toomas Soome	{ 0x2202, 0xeb, 0x00 }, { 0x2208, 0xee, 0x00 },
3909890ff8Toomas Soome	{ 0x2211, 0xe4, 0x00 }, { 0x2212, 0x2d, 0x00 },
3919890ff8Toomas Soome	{ 0x2219, 0xf9, 0x00 }, { 0x221a, 0xfb, 0x00 },
3929890ff8Toomas Soome	{ 0x221e, 0xec, 0x00 }, { 0x221f, 0x1c, 0x00 },
3939890ff8Toomas Soome	{ 0x2229, 0xef, 0x00 }, { 0x2248, 0xf7, 0x00 },
3949890ff8Toomas Soome	{ 0x2261, 0xf0, 0x00 }, { 0x2264, 0xf3, 0x00 },
3959890ff8Toomas Soome	{ 0x2265, 0xf2, 0x00 }, { 0x2302, 0x7f, 0x00 },
3969890ff8Toomas Soome	{ 0x2310, 0xa9, 0x00 }, { 0x2320, 0xf4, 0x00 },
3979890ff8Toomas Soome	{ 0x2321, 0xf5, 0x00 }, { 0x2500, 0xc4, 0x00 },
3989890ff8Toomas Soome	{ 0x2502, 0xb3, 0x00 }, { 0x250c, 0xda, 0x00 },
3999890ff8Toomas Soome	{ 0x2510, 0xbf, 0x00 }, { 0x2514, 0xc0, 0x00 },
4009890ff8Toomas Soome	{ 0x2518, 0xd9, 0x00 }, { 0x251c, 0xc3, 0x00 },
4019890ff8Toomas Soome	{ 0x2524, 0xb4, 0x00 }, { 0x252c, 0xc2, 0x00 },
4029890ff8Toomas Soome	{ 0x2534, 0xc1, 0x00 }, { 0x253c, 0xc5, 0x00 },
4039890ff8Toomas Soome	{ 0x2550, 0xcd, 0x00 }, { 0x2551, 0xba, 0x00 },
4049890ff8Toomas Soome	{ 0x2552, 0xd5, 0x00 }, { 0x2553, 0xd6, 0x00 },
4059890ff8Toomas Soome	{ 0x2554, 0xc9, 0x00 }, { 0x2555, 0xb8, 0x00 },
4069890ff8Toomas Soome	{ 0x2556, 0xb7, 0x00 }, { 0x2557, 0xbb, 0x00 },
4079890ff8Toomas Soome	{ 0x2558, 0xd4, 0x00 }, { 0x2559, 0xd3, 0x00 },
4089890ff8Toomas Soome	{ 0x255a, 0xc8, 0x00 }, { 0x255b, 0xbe, 0x00 },
4099890ff8Toomas Soome	{ 0x255c, 0xbd, 0x00 }, { 0x255d, 0xbc, 0x00 },
4109890ff8Toomas Soome	{ 0x255e, 0xc6, 0x01 }, { 0x2560, 0xcc, 0x00 },
4119890ff8Toomas Soome	{ 0x2561, 0xb5, 0x00 }, { 0x2562, 0xb6, 0x00 },
4129890ff8Toomas Soome	{ 0x2563, 0xb9, 0x00 }, { 0x2564, 0xd1, 0x01 },
4139890ff8Toomas Soome	{ 0x2566, 0xcb, 0x00 }, { 0x2567, 0xcf, 0x00 },
4149890ff8Toomas Soome	{ 0x2568, 0xd0, 0x00 }, { 0x2569, 0xca, 0x00 },
4159890ff8Toomas Soome	{ 0x256a, 0xd8, 0x00 }, { 0x256b, 0xd7, 0x00 },
4169890ff8Toomas Soome	{ 0x256c, 0xce, 0x00 }, { 0x2580, 0xdf, 0x00 },
4179890ff8Toomas Soome	{ 0x2584, 0xdc, 0x00 }, { 0x2588, 0xdb, 0x00 },
4189890ff8Toomas Soome	{ 0x258c, 0xdd, 0x00 }, { 0x2590, 0xde, 0x00 },
4199890ff8Toomas Soome	{ 0x2591, 0xb0, 0x02 }, { 0x25a0, 0xfe, 0x00 },
4209890ff8Toomas Soome	{ 0x25ac, 0x16, 0x00 }, { 0x25b2, 0x1e, 0x00 },
4219890ff8Toomas Soome	{ 0x25ba, 0x10, 0x00 }, { 0x25bc, 0x1f, 0x00 },
4229890ff8Toomas Soome	{ 0x25c4, 0x11, 0x00 }, { 0x25cb, 0x09, 0x00 },
4239890ff8Toomas Soome	{ 0x25d8, 0x08, 0x00 }, { 0x25d9, 0x0a, 0x00 },
4249890ff8Toomas Soome	{ 0x263a, 0x01, 0x01 }, { 0x263c, 0x0f, 0x00 },
4259890ff8Toomas Soome	{ 0x2640, 0x0c, 0x00 }, { 0x2642, 0x0b, 0x00 },
4269890ff8Toomas Soome	{ 0x2660, 0x06, 0x00 }, { 0x2663, 0x05, 0x00 },
4279890ff8Toomas Soome	{ 0x2665, 0x03, 0x01 }, { 0x266a, 0x0d, 0x00 },
4289890ff8Toomas Soome	{ 0x266c, 0x0e, 0x00 }
4299890ff8Toomas Soome};
430199767fToomas Soome
4319890ff8Toomas Soomestatic uint8_t
4329890ff8Toomas Soomevga_get_cp437(tem_char_t c)
433199767fToomas Soome{
4349890ff8Toomas Soome	int min, mid, max;
4359890ff8Toomas Soome
4369890ff8Toomas Soome	min = 0;
437c7832f2Toomas Soome	max = (sizeof (cp437table) / sizeof (struct unicp437)) - 1;
4389890ff8Toomas Soome
4399890ff8Toomas Soome	if (c < cp437table[0].unicode_base ||
4409890ff8Toomas Soome	    c > cp437table[max].unicode_base + cp437table[max].length)
4419890ff8Toomas Soome		return ('?');
4429890ff8Toomas Soome
4439890ff8Toomas Soome	while (max >= min) {
4449890ff8Toomas Soome		mid = (min + max) / 2;
4459890ff8Toomas Soome		if (c < cp437table[mid].unicode_base)
4469890ff8Toomas Soome			max = mid - 1;
4479890ff8Toomas Soome		else if (c > cp437table[mid].unicode_base +
4489890ff8Toomas Soome		    cp437table[mid].length)
4499890ff8Toomas Soome			min = mid + 1;
450c7832f2Toomas Soome		else
4519890ff8Toomas Soome			return (c - cp437table[mid].unicode_base +
4529890ff8Toomas Soome			    cp437table[mid].cp437_base);
453c7832f2Toomas Soome	}
4549890ff8Toomas Soome
4559890ff8Toomas Soome	return ('?');
456199767fToomas Soome}
457199767fToomas Soome
4589890ff8Toomas Soomestatic void
4599890ff8Toomas Soomevidc_text_cons_display(struct vis_consdisplay *da)
460199767fToomas Soome{
4619890ff8Toomas Soome	int i;
4629890ff8Toomas Soome	uint8_t attr;
4639890ff8Toomas Soome	tem_char_t *data;
4649890ff8Toomas Soome	struct cgatext {
4659890ff8Toomas Soome		uint8_t ch;
4669890ff8Toomas Soome		uint8_t attr;
4679890ff8Toomas Soome	} *addr;
4689890ff8Toomas Soome
4699890ff8Toomas Soome	data = (tem_char_t *)da->data;
4709890ff8Toomas Soome	attr = (solaris_color_to_pc_color[da->bg_color & 0xf] << 4) |
4719890ff8Toomas Soome	    solaris_color_to_pc_color[da->fg_color & 0xf];
472c7832f2Toomas Soome	addr = (struct cgatext *)vgatext + (da->row * TEXT_COLS + da->col);
4739890ff8Toomas Soome
4749890ff8Toomas Soome	for (i = 0; i < da->width; i++) {
4759890ff8Toomas Soome		addr[i].ch = vga_get_cp437(data[i]);
4769890ff8Toomas Soome		addr[i].attr = attr;
4779890ff8Toomas Soome	}
478199767fToomas Soome}
479199767fToomas Soome
4809890ff8Toomas Soomestatic void
4819890ff8Toomas Soomevidc_text_set_cursor(screen_pos_t row, screen_pos_t col, boolean_t visible)
482199767fToomas Soome{
4839890ff8Toomas Soome	uint16_t addr;
4849890ff8Toomas Soome	uint8_t msl, s, e;
4859890ff8Toomas Soome
4869890ff8Toomas Soome	msl = vga_get_crtc(VGA_REG_ADDR, VGA_CRTC_MAX_S_LN) & 0x1f;
4879890ff8Toomas Soome	s = vga_get_crtc(VGA_REG_ADDR, VGA_CRTC_CSSL) & 0xC0;
4889890ff8Toomas Soome	e = vga_get_crtc(VGA_REG_ADDR, VGA_CRTC_CESL);
4899890ff8Toomas Soome
4909890ff8Toomas Soome	if (visible == B_TRUE) {
4919890ff8Toomas Soome		addr = row * TEXT_COLS + col;
4929890ff8Toomas Soome		vga_set_crtc(VGA_REG_ADDR, VGA_CRTC_CLAH, addr >> 8);
4939890ff8Toomas Soome		vga_set_crtc(VGA_REG_ADDR, VGA_CRTC_CLAL, addr & 0xff);
4949890ff8Toomas Soome		e = msl;
4959890ff8Toomas Soome	} else {
4969890ff8Toomas Soome		s |= (1<<5);
497199767fToomas Soome	}
4989890ff8Toomas Soome	vga_set_crtc(VGA_REG_ADDR, VGA_CRTC_CSSL, s);
4999890ff8Toomas Soome	vga_set_crtc(VGA_REG_ADDR, VGA_CRTC_CESL, e);
500