aboutsummaryrefslogtreecommitdiff
path: root/stand/i386/libi386
diff options
context:
space:
mode:
authorToomas Soome <tsoome@FreeBSD.org>2019-09-05 22:15:50 +0000
committerToomas Soome <tsoome@FreeBSD.org>2019-09-05 22:15:50 +0000
commit56758831fe6c5702d3a76a2ea12986a5bf978ef5 (patch)
tree7f7812435384549919ad6d65ee72fa7d4464f9e1 /stand/i386/libi386
parenta6935d085cc66db547a472030a91bbf57f358737 (diff)
downloadsrc-56758831fe6c5702d3a76a2ea12986a5bf978ef5.tar.gz
src-56758831fe6c5702d3a76a2ea12986a5bf978ef5.zip
loader: use teken teminal emulator for x86 and uefi
Replace mini cons25 emulator with teken, this does enable us proper console terminal for loader and will make it possible to implement different back end callbacks to draw to screen. At this time we still only "draw" in text mode.
Notes
Notes: svn path=/head/; revision=351900
Diffstat (limited to 'stand/i386/libi386')
-rw-r--r--stand/i386/libi386/Makefile8
-rw-r--r--stand/i386/libi386/vidconsole.c1078
2 files changed, 632 insertions, 454 deletions
diff --git a/stand/i386/libi386/Makefile b/stand/i386/libi386/Makefile
index 653d00d3c1b6..d6667a548ccf 100644
--- a/stand/i386/libi386/Makefile
+++ b/stand/i386/libi386/Makefile
@@ -14,6 +14,9 @@ SRCS= bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \
SRCS+= devicename_stubs.c
CFLAGS+= -I${ZFSSRC}
+.PATH: ${SYSDIR}/teken
+SRCS+= teken.c
+
BOOT_COMCONSOLE_PORT?= 0x3f8
CFLAGS+= -DCOMPORT=${BOOT_COMCONSOLE_PORT}
@@ -37,8 +40,9 @@ CFLAGS+= -DSMBIOS_NETWORK_ENDIAN_UUID
.endif
.endif
-# Include simple terminal emulation (cons25-compatible)
-CFLAGS+= -DTERM_EMU
+# terminal emulation
+CFLAGS.vidconsole.c+= -I${SRCTOP}/sys/teken
+CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
# XXX: make alloca() useable
CFLAGS+= -Dalloca=__builtin_alloca
diff --git a/stand/i386/libi386/vidconsole.c b/stand/i386/libi386/vidconsole.c
index a045cff396f3..854a7f16e4cc 100644
--- a/stand/i386/libi386/vidconsole.c
+++ b/stand/i386/libi386/vidconsole.c
@@ -34,11 +34,15 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <btxv86.h>
#include <machine/psl.h>
+#include <machine/cpufunc.h>
+#include <teken.h>
+#include <stdbool.h>
+
+#include <dev/vt/hw/vga/vt_vga_reg.h>
+
#include "libi386.h"
#if KEYBOARD_PROBE
-#include <machine/cpufunc.h>
-
static int probe_keyboard(void);
#endif
static void vidc_probe(struct console *cp);
@@ -48,490 +52,658 @@ static int vidc_getchar(void);
static int vidc_ischar(void);
static int vidc_started;
+static uint16_t *vgatext;
+
+static tf_bell_t vidc_cons_bell;
+static tf_cursor_t vidc_text_cursor;
+static tf_putchar_t vidc_text_putchar;
+static tf_fill_t vidc_text_fill;
+static tf_copy_t vidc_text_copy;
+static tf_param_t vidc_text_param;
+static tf_respond_t vidc_cons_respond;
+
+static teken_funcs_t tf = {
+ .tf_bell = vidc_cons_bell,
+ .tf_cursor = vidc_text_cursor,
+ .tf_putchar = vidc_text_putchar,
+ .tf_fill = vidc_text_fill,
+ .tf_copy = vidc_text_copy,
+ .tf_param = vidc_text_param,
+ .tf_respond = vidc_cons_respond,
+};
-void get_pos(int *x, int *y);
-
-#ifdef TERM_EMU
-#define MAXARGS 8
-#define DEFAULT_FGCOLOR 7
-#define DEFAULT_BGCOLOR 0
-
-void end_term(void);
-void bail_out(int c);
-void vidc_term_emu(int c);
-void curs_move(int *_x, int *_y, int x, int y);
-void write_char(int c, int fg, int bg);
-void scroll_up(int rows, int fg, int bg);
-void CD(void);
-void CM(void);
-void HO(void);
-
-static int args[MAXARGS], argc;
-static int fg_c, bg_c, curx, cury;
-static int esc;
-#endif
+teken_t teken;
+teken_pos_t tp;
+struct text_pixel {
+ teken_char_t c;
+ teken_attr_t a;
+};
+
+static struct text_pixel *buffer;
+
+#define NCOLORS 16
+
+/*
+ * Between console's palette and VGA's one:
+ * - blue and red are swapped (1 <-> 4)
+ * - yellow and cyan are swapped (3 <-> 6)
+ */
+static const int cons_to_vga_colors[NCOLORS] = {
+ 0, 4, 2, 6, 1, 5, 3, 7,
+ 8, 12, 10, 14, 9, 13, 11, 15
+};
+
+#define TEXT_COLS 80
+#define TEXT_ROWS 25
+#define KEYBUFSZ 10
+
+static uint8_t keybuf[KEYBUFSZ]; /* keybuf for extended codes */
struct console vidconsole = {
- "vidconsole",
- "internal video/keyboard",
- 0,
- vidc_probe,
- vidc_init,
- vidc_putchar,
- vidc_getchar,
- vidc_ischar
+ .c_name = "vidconsole",
+ .c_desc = "internal video/keyboard",
+ .c_flags = 0,
+ .c_probe = vidc_probe,
+ .c_init = vidc_init,
+ .c_out = vidc_putchar,
+ .c_in = vidc_getchar,
+ .c_ready = vidc_ischar
};
-static void
-vidc_probe(struct console *cp)
+static int
+vga_get_reg(int reg, int index)
{
-
- /* look for a keyboard */
-#if KEYBOARD_PROBE
- if (probe_keyboard())
-#endif
- {
-
- cp->c_flags |= C_PRESENTIN;
- }
-
- /* XXX for now, always assume we can do BIOS screen output */
- cp->c_flags |= C_PRESENTOUT;
+ return (inb(reg + index));
}
static int
-vidc_init(int arg)
+vga_get_atr(int reg, int i)
{
- int i;
+ int ret;
- if (vidc_started && arg == 0)
- return (0);
- vidc_started = 1;
-#ifdef TERM_EMU
- /* Init terminal emulator */
- end_term();
- get_pos(&curx, &cury);
- curs_move(&curx, &cury, curx, cury);
- fg_c = DEFAULT_FGCOLOR;
- bg_c = DEFAULT_BGCOLOR;
-#endif
- for (i = 0; i < 10 && vidc_ischar(); i++)
- (void)vidc_getchar();
- return (0); /* XXX reinit? */
-}
+ (void) inb(reg + VGA_GEN_INPUT_STAT_1);
+ outb(reg + VGA_AC_WRITE, i);
+ ret = inb(reg + VGA_AC_READ);
-void
-vidc_biosputchar(int c)
-{
+ (void) inb(reg + VGA_GEN_INPUT_STAT_1);
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0xe00 | (c & 0xff);
- v86.ebx = 0x7;
- v86int();
+ return (ret);
}
static void
-vidc_rawputchar(int c)
+vga_set_atr(int reg, int i, int v)
{
- int i;
+ (void) inb(reg + VGA_GEN_INPUT_STAT_1);
+ outb(reg + VGA_AC_WRITE, i);
+ outb(reg + VGA_AC_WRITE, v);
- if (c == '\t') {
- int n;
-#ifndef TERM_EMU
- int curx, cury;
+ (void) inb(reg + VGA_GEN_INPUT_STAT_1);
+}
- get_pos(&curx, %cury);
-#endif
+static void
+vga_set_indexed(int reg, int indexreg, int datareg, uint8_t index, uint8_t val)
+{
+ outb(reg + indexreg, index);
+ outb(reg + datareg, val);
+}
- n = 8 - ((curx + 8) % 8);
- for (i = 0; i < n; i++)
- vidc_rawputchar(' ');
- } else {
-#ifndef TERM_EMU
- vidc_biosputchar(c);
-#else
- /* Emulate AH=0eh (teletype output) */
- switch(c) {
- case '\a':
- vidc_biosputchar(c);
- return;
- case '\r':
- curx = 0;
- curs_move(&curx, &cury, curx, cury);
- return;
- case '\n':
- cury++;
- if (cury > 24) {
- scroll_up(1, fg_c, bg_c);
- cury--;
- } else {
- curs_move(&curx, &cury, curx, cury);
- }
- return;
- case '\b':
- if (curx > 0) {
- curx--;
- curs_move(&curx, &cury, curx, cury);
- /* write_char(' ', fg_c, bg_c); XXX destructive(!) */
- return;
- }
- return;
- default:
- write_char(c, fg_c, bg_c);
- curx++;
- if (curx > 79) {
- curx = 0;
- cury++;
- }
- if (cury > 24) {
- curx = 0;
- scroll_up(1, fg_c, bg_c);
- cury--;
- }
- }
- curs_move(&curx, &cury, curx, cury);
-#endif
- }
+static int
+vga_get_indexed(int reg, int indexreg, int datareg, uint8_t index)
+{
+ outb(reg + indexreg, index);
+ return (inb(reg + datareg));
}
-/* Get cursor position on the screen. Result is in edx. Sets
- * curx and cury appropriately.
- */
-void
-get_pos(int *x, int *y)
+static int
+vga_get_crtc(int reg, int i)
{
+ return (vga_get_indexed(reg, VGA_CRTC_ADDRESS, VGA_CRTC_DATA, i));
+}
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0300;
- v86.ebx = 0x0;
- v86int();
- *x = v86.edx & 0x00ff;
- *y = (v86.edx & 0xff00) >> 8;
+static void
+vga_set_crtc(int reg, int i, int v)
+{
+ vga_set_indexed(reg, VGA_CRTC_ADDRESS, VGA_CRTC_DATA, i, v);
}
-#ifdef TERM_EMU
+static void
+vidc_text_set_cursor(teken_unit_t row, teken_unit_t col, bool visible)
+{
+ uint16_t addr;
+ uint8_t msl, s, e;
+
+ msl = vga_get_crtc(VGA_REG_BASE, VGA_CRTC_MAX_SCAN_LINE) & 0x1f;
+ s = vga_get_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_START) & 0xC0;
+ e = vga_get_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_END);
+
+ if (visible == true) {
+ addr = row * TEXT_COLS + col;
+ vga_set_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_LOC_HIGH, addr >> 8);
+ vga_set_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_LOC_LOW,
+ addr & 0xff);
+ e = msl;
+ } else {
+ s |= (1<<5);
+ }
+ vga_set_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_START, s);
+ vga_set_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_END, e);
+}
-/* Move cursor to x rows and y cols (0-based). */
-void
-curs_move(int *_x, int *_y, int x, int y)
+static void
+vidc_text_get_cursor(teken_unit_t *row, teken_unit_t *col)
{
+ uint16_t addr;
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0200;
- v86.ebx = 0x0;
- v86.edx = ((0x00ff & y) << 8) + (0x00ff & x);
- v86int();
- *_x = x;
- *_y = y;
- /* If there is ctrl char at this position, cursor would be invisible.
- * Make it a space instead.
- */
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0800;
- v86.ebx = 0x0;
- v86int();
-#define isvisible(c) (((c) >= 32) && ((c) < 255))
- if (!isvisible(v86.eax & 0x00ff)) {
- write_char(' ', fg_c, bg_c);
- }
+ addr = (vga_get_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_LOC_HIGH) << 8) +
+ vga_get_crtc(VGA_REG_BASE, VGA_CRTC_CURSOR_LOC_LOW);
+
+ *row = addr / TEXT_COLS;
+ *col = addr % TEXT_COLS;
}
-/* Scroll up the whole window by a number of rows. If rows==0,
- * clear the window. fg and bg are attributes for the new lines
- * inserted in the window.
+/*
+ * Not implemented.
*/
-void
-scroll_up(int rows, int fgcol, int bgcol)
+static void
+vidc_cons_bell(void *s __unused)
{
-
- if (rows == 0)
- rows = 25;
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0600 + (0x00ff & rows);
- v86.ebx = (bgcol << 12) + (fgcol << 8);
- v86.ecx = 0x0;
- v86.edx = 0x184f;
- v86int();
}
-/* Write character and attribute at cursor position. */
-void
-write_char(int c, int fgcol, int bgcol)
+static void
+vidc_text_cursor(void *s __unused, const teken_pos_t *p)
{
+ teken_unit_t row, col;
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0900 + (0x00ff & c);
- v86.ebx = (bgcol << 4) + fgcol;
- v86.ecx = 0x1;
- v86int();
+ if (p->tp_col == TEXT_COLS)
+ col = p->tp_col - 1;
+ else
+ col = p->tp_col;
+
+ if (p->tp_row == TEXT_ROWS)
+ row = p->tp_row - 1;
+ else
+ row = p->tp_row;
+
+ vidc_text_set_cursor(row, col, true);
}
-/**************************************************************/
/*
- * Screen manipulation functions. They use accumulated data in
- * args[] and argc variables.
- *
+ * Binary searchable table for Unicode to CP437 conversion.
*/
+struct unicp437 {
+ uint16_t unicode_base;
+ uint8_t cp437_base;
+ uint8_t length;
+};
-/* Clear display from current position to end of screen */
-void
-CD(void)
-{
+static const struct unicp437 cp437table[] = {
+ { 0x0020, 0x20, 0x5e }, { 0x00a0, 0x20, 0x00 },
+ { 0x00a1, 0xad, 0x00 }, { 0x00a2, 0x9b, 0x00 },
+ { 0x00a3, 0x9c, 0x00 }, { 0x00a5, 0x9d, 0x00 },
+ { 0x00a7, 0x15, 0x00 }, { 0x00aa, 0xa6, 0x00 },
+ { 0x00ab, 0xae, 0x00 }, { 0x00ac, 0xaa, 0x00 },
+ { 0x00b0, 0xf8, 0x00 }, { 0x00b1, 0xf1, 0x00 },
+ { 0x00b2, 0xfd, 0x00 }, { 0x00b5, 0xe6, 0x00 },
+ { 0x00b6, 0x14, 0x00 }, { 0x00b7, 0xfa, 0x00 },
+ { 0x00ba, 0xa7, 0x00 }, { 0x00bb, 0xaf, 0x00 },
+ { 0x00bc, 0xac, 0x00 }, { 0x00bd, 0xab, 0x00 },
+ { 0x00bf, 0xa8, 0x00 }, { 0x00c4, 0x8e, 0x01 },
+ { 0x00c6, 0x92, 0x00 }, { 0x00c7, 0x80, 0x00 },
+ { 0x00c9, 0x90, 0x00 }, { 0x00d1, 0xa5, 0x00 },
+ { 0x00d6, 0x99, 0x00 }, { 0x00dc, 0x9a, 0x00 },
+ { 0x00df, 0xe1, 0x00 }, { 0x00e0, 0x85, 0x00 },
+ { 0x00e1, 0xa0, 0x00 }, { 0x00e2, 0x83, 0x00 },
+ { 0x00e4, 0x84, 0x00 }, { 0x00e5, 0x86, 0x00 },
+ { 0x00e6, 0x91, 0x00 }, { 0x00e7, 0x87, 0x00 },
+ { 0x00e8, 0x8a, 0x00 }, { 0x00e9, 0x82, 0x00 },
+ { 0x00ea, 0x88, 0x01 }, { 0x00ec, 0x8d, 0x00 },
+ { 0x00ed, 0xa1, 0x00 }, { 0x00ee, 0x8c, 0x00 },
+ { 0x00ef, 0x8b, 0x00 }, { 0x00f0, 0xeb, 0x00 },
+ { 0x00f1, 0xa4, 0x00 }, { 0x00f2, 0x95, 0x00 },
+ { 0x00f3, 0xa2, 0x00 }, { 0x00f4, 0x93, 0x00 },
+ { 0x00f6, 0x94, 0x00 }, { 0x00f7, 0xf6, 0x00 },
+ { 0x00f8, 0xed, 0x00 }, { 0x00f9, 0x97, 0x00 },
+ { 0x00fa, 0xa3, 0x00 }, { 0x00fb, 0x96, 0x00 },
+ { 0x00fc, 0x81, 0x00 }, { 0x00ff, 0x98, 0x00 },
+ { 0x0192, 0x9f, 0x00 }, { 0x0393, 0xe2, 0x00 },
+ { 0x0398, 0xe9, 0x00 }, { 0x03a3, 0xe4, 0x00 },
+ { 0x03a6, 0xe8, 0x00 }, { 0x03a9, 0xea, 0x00 },
+ { 0x03b1, 0xe0, 0x01 }, { 0x03b4, 0xeb, 0x00 },
+ { 0x03b5, 0xee, 0x00 }, { 0x03bc, 0xe6, 0x00 },
+ { 0x03c0, 0xe3, 0x00 }, { 0x03c3, 0xe5, 0x00 },
+ { 0x03c4, 0xe7, 0x00 }, { 0x03c6, 0xed, 0x00 },
+ { 0x03d5, 0xed, 0x00 }, { 0x2010, 0x2d, 0x00 },
+ { 0x2014, 0x2d, 0x00 }, { 0x2018, 0x60, 0x00 },
+ { 0x2019, 0x27, 0x00 }, { 0x201c, 0x22, 0x00 },
+ { 0x201d, 0x22, 0x00 }, { 0x2022, 0x07, 0x00 },
+ { 0x203c, 0x13, 0x00 }, { 0x207f, 0xfc, 0x00 },
+ { 0x20a7, 0x9e, 0x00 }, { 0x20ac, 0xee, 0x00 },
+ { 0x2126, 0xea, 0x00 }, { 0x2190, 0x1b, 0x00 },
+ { 0x2191, 0x18, 0x00 }, { 0x2192, 0x1a, 0x00 },
+ { 0x2193, 0x19, 0x00 }, { 0x2194, 0x1d, 0x00 },
+ { 0x2195, 0x12, 0x00 }, { 0x21a8, 0x17, 0x00 },
+ { 0x2202, 0xeb, 0x00 }, { 0x2208, 0xee, 0x00 },
+ { 0x2211, 0xe4, 0x00 }, { 0x2212, 0x2d, 0x00 },
+ { 0x2219, 0xf9, 0x00 }, { 0x221a, 0xfb, 0x00 },
+ { 0x221e, 0xec, 0x00 }, { 0x221f, 0x1c, 0x00 },
+ { 0x2229, 0xef, 0x00 }, { 0x2248, 0xf7, 0x00 },
+ { 0x2261, 0xf0, 0x00 }, { 0x2264, 0xf3, 0x00 },
+ { 0x2265, 0xf2, 0x00 }, { 0x2302, 0x7f, 0x00 },
+ { 0x2310, 0xa9, 0x00 }, { 0x2320, 0xf4, 0x00 },
+ { 0x2321, 0xf5, 0x00 }, { 0x2500, 0xc4, 0x00 },
+ { 0x2502, 0xb3, 0x00 }, { 0x250c, 0xda, 0x00 },
+ { 0x2510, 0xbf, 0x00 }, { 0x2514, 0xc0, 0x00 },
+ { 0x2518, 0xd9, 0x00 }, { 0x251c, 0xc3, 0x00 },
+ { 0x2524, 0xb4, 0x00 }, { 0x252c, 0xc2, 0x00 },
+ { 0x2534, 0xc1, 0x00 }, { 0x253c, 0xc5, 0x00 },
+ { 0x2550, 0xcd, 0x00 }, { 0x2551, 0xba, 0x00 },
+ { 0x2552, 0xd5, 0x00 }, { 0x2553, 0xd6, 0x00 },
+ { 0x2554, 0xc9, 0x00 }, { 0x2555, 0xb8, 0x00 },
+ { 0x2556, 0xb7, 0x00 }, { 0x2557, 0xbb, 0x00 },
+ { 0x2558, 0xd4, 0x00 }, { 0x2559, 0xd3, 0x00 },
+ { 0x255a, 0xc8, 0x00 }, { 0x255b, 0xbe, 0x00 },
+ { 0x255c, 0xbd, 0x00 }, { 0x255d, 0xbc, 0x00 },
+ { 0x255e, 0xc6, 0x01 }, { 0x2560, 0xcc, 0x00 },
+ { 0x2561, 0xb5, 0x00 }, { 0x2562, 0xb6, 0x00 },
+ { 0x2563, 0xb9, 0x00 }, { 0x2564, 0xd1, 0x01 },
+ { 0x2566, 0xcb, 0x00 }, { 0x2567, 0xcf, 0x00 },
+ { 0x2568, 0xd0, 0x00 }, { 0x2569, 0xca, 0x00 },
+ { 0x256a, 0xd8, 0x00 }, { 0x256b, 0xd7, 0x00 },
+ { 0x256c, 0xce, 0x00 }, { 0x2580, 0xdf, 0x00 },
+ { 0x2584, 0xdc, 0x00 }, { 0x2588, 0xdb, 0x00 },
+ { 0x258c, 0xdd, 0x00 }, { 0x2590, 0xde, 0x00 },
+ { 0x2591, 0xb0, 0x02 }, { 0x25a0, 0xfe, 0x00 },
+ { 0x25ac, 0x16, 0x00 }, { 0x25b2, 0x1e, 0x00 },
+ { 0x25ba, 0x10, 0x00 }, { 0x25bc, 0x1f, 0x00 },
+ { 0x25c4, 0x11, 0x00 }, { 0x25cb, 0x09, 0x00 },
+ { 0x25d8, 0x08, 0x00 }, { 0x25d9, 0x0a, 0x00 },
+ { 0x263a, 0x01, 0x01 }, { 0x263c, 0x0f, 0x00 },
+ { 0x2640, 0x0c, 0x00 }, { 0x2642, 0x0b, 0x00 },
+ { 0x2660, 0x06, 0x00 }, { 0x2663, 0x05, 0x00 },
+ { 0x2665, 0x03, 0x01 }, { 0x266a, 0x0d, 0x00 },
+ { 0x266c, 0x0e, 0x00 }
+};
- get_pos(&curx, &cury);
- if (curx > 0) {
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0600;
- v86.ebx = (bg_c << 4) + fg_c;
- v86.ecx = (cury << 8) + curx;
- v86.edx = (cury << 8) + 79;
- v86int();
- if (++cury > 24) {
- end_term();
- return;
+static uint8_t
+vga_get_cp437(teken_char_t c)
+{
+ int min, mid, max;
+
+ min = 0;
+ max = (sizeof(cp437table) / sizeof(struct unicp437)) - 1;
+
+ if (c < cp437table[0].unicode_base ||
+ c > cp437table[max].unicode_base + cp437table[max].length)
+ return ('?');
+
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (c < cp437table[mid].unicode_base)
+ max = mid - 1;
+ else if (c > cp437table[mid].unicode_base +
+ cp437table[mid].length)
+ min = mid + 1;
+ else
+ return (c - cp437table[mid].unicode_base +
+ cp437table[mid].cp437_base);
}
- }
- v86.ctl = 0;
- v86.addr = 0x10;
- v86.eax = 0x0600;
- v86.ebx = (bg_c << 4) + fg_c;
- v86.ecx = (cury << 8) + 0;
- v86.edx = (24 << 8) + 79;
- v86int();
- end_term();
+
+ return ('?');
}
-/* Absolute cursor move to args[0] rows and args[1] columns
- * (the coordinates are 1-based).
- */
-void
-CM(void)
+static void
+vidc_text_printchar(const teken_pos_t *p)
{
+ int i;
+ uint8_t attr;
+ struct text_pixel *px;
+ teken_color_t fg, bg, tmp;
+ struct cgatext {
+ uint8_t ch;
+ uint8_t attr;
+ } *addr;
+
+ px = buffer + p->tp_col + p->tp_row * tp.tp_col;
+ fg = teken_256to16(px->a.ta_fgcolor);
+ bg = teken_256to16(px->a.ta_bgcolor);
+ if (px->a.ta_format & TF_BOLD)
+ fg |= TC_LIGHT;
+ if (px->a.ta_format & TF_BLINK)
+ bg |= TC_LIGHT;
+
+ if (px->a.ta_format & TF_REVERSE) {
+ tmp = fg;
+ fg = bg;
+ bg = tmp;
+ }
- if (args[0] > 0)
- args[0]--;
- if (args[1] > 0)
- args[1]--;
- curs_move(&curx, &cury, args[1], args[0]);
- end_term();
+ attr = (cons_to_vga_colors[bg & 0xf] << 4) |
+ cons_to_vga_colors[fg & 0xf];
+ addr = (struct cgatext *)vgatext + p->tp_col + p->tp_row * tp.tp_col;
+ addr->ch = vga_get_cp437(px->c);
+ addr->attr = attr;
}
-/* Home cursor (left top corner) */
-void
-HO(void)
+static void
+vidc_text_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c,
+ const teken_attr_t *a)
{
+ int attr, idx;
- argc = 1;
- args[0] = args[1] = 1;
- CM();
+ idx = p->tp_col + p->tp_row * tp.tp_col;
+ buffer[idx].c = c;
+ buffer[idx].a = *a;
+ vidc_text_printchar(p);
}
-/* Clear internal state of the terminal emulation code */
-void
-end_term(void)
+static void
+vidc_text_fill(void *s, const teken_rect_t *r, teken_char_t c,
+ const teken_attr_t *a)
+{
+ teken_pos_t p;
+ teken_unit_t row, col;
+
+ vidc_text_get_cursor(&row, &col);
+ vidc_text_set_cursor(row, col, false);
+ for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row;
+ p.tp_row++)
+ for (p.tp_col = r->tr_begin.tp_col;
+ p.tp_col < r->tr_end.tp_col; p.tp_col++)
+ vidc_text_putchar(s, &p, c, a);
+ vidc_text_set_cursor(row, col, true);
+}
+
+static bool
+vidc_same_pixel(struct text_pixel *px1, struct text_pixel *px2)
{
+ if (px1->c != px2->c)
+ return (false);
+
+ if (px1->a.ta_format != px2->a.ta_format)
+ return (false);
+ if (px1->a.ta_fgcolor != px2->a.ta_fgcolor)
+ return (false);
+ if (px1->a.ta_bgcolor != px2->a.ta_bgcolor)
+ return (false);
- esc = 0;
- argc = -1;
+ return (true);
}
-/* Gracefully exit ESC-sequence processing in case of misunderstanding */
-void
-bail_out(int c)
+static void
+vidc_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
{
- char buf[16], *ch;
- int i;
-
- if (esc) {
- vidc_rawputchar('\033');
- if (esc != '\033')
- vidc_rawputchar(esc);
- for (i = 0; i <= argc; ++i) {
- sprintf(buf, "%d", args[i]);
- ch = buf;
- while (*ch)
- vidc_rawputchar(*ch++);
+ int srow, drow;
+ int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */
+ teken_pos_t d, s;
+ teken_unit_t row, col;
+
+ /*
+ * Copying is a little tricky. We must make sure we do it in
+ * correct order, to make sure we don't overwrite our own data.
+ */
+
+ nrow = r->tr_end.tp_row - r->tr_begin.tp_row;
+ ncol = r->tr_end.tp_col - r->tr_begin.tp_col;
+
+ vidc_text_get_cursor(&row, &col);
+ vidc_text_set_cursor(row, col, false);
+ if (p->tp_row < r->tr_begin.tp_row) {
+ /* Copy from bottom to top. */
+ for (y = 0; y < nrow; y++) {
+ d.tp_row = p->tp_row + y;
+ s.tp_row = r->tr_begin.tp_row + y;
+ drow = d.tp_row * tp.tp_col;
+ srow = s.tp_row * tp.tp_col;
+ for (x = 0; x < ncol; x++) {
+ d.tp_col = p->tp_col + x;
+ s.tp_col = r->tr_begin.tp_col + x;
+
+ if (!vidc_same_pixel(
+ &buffer[d.tp_col + drow],
+ &buffer[s.tp_col + srow])) {
+ buffer[d.tp_col + drow] =
+ buffer[s.tp_col + srow];
+ vidc_text_printchar(&d);
+ }
+ }
+ }
+ } else {
+ /* Copy from top to bottom. */
+ if (p->tp_col < r->tr_begin.tp_col) {
+ /* Copy from right to left. */
+ for (y = nrow - 1; y >= 0; y--) {
+ d.tp_row = p->tp_row + y;
+ s.tp_row = r->tr_begin.tp_row + y;
+ drow = d.tp_row * tp.tp_col;
+ srow = s.tp_row * tp.tp_col;
+ for (x = 0; x < ncol; x++) {
+ d.tp_col = p->tp_col + x;
+ s.tp_col = r->tr_begin.tp_col + x;
+
+ if (!vidc_same_pixel(
+ &buffer[d.tp_col + drow],
+ &buffer[s.tp_col + srow])) {
+ buffer[d.tp_col + drow] =
+ buffer[s.tp_col + srow];
+ vidc_text_printchar(&d);
+ }
+ }
+ }
+ } else {
+ /* Copy from left to right. */
+ for (y = nrow - 1; y >= 0; y--) {
+ d.tp_row = p->tp_row + y;
+ s.tp_row = r->tr_begin.tp_row + y;
+ drow = d.tp_row * tp.tp_col;
+ srow = s.tp_row * tp.tp_col;
+ for (x = ncol - 1; x >= 0; x--) {
+ d.tp_col = p->tp_col + x;
+ s.tp_col = r->tr_begin.tp_col + x;
+
+ if (!vidc_same_pixel(
+ &buffer[d.tp_col + drow],
+ &buffer[s.tp_col + srow])) {
+ buffer[d.tp_col + drow] =
+ buffer[s.tp_col + srow];
+ vidc_text_printchar(&d);
+ }
+ }
+ }
+ }
}
- }
- vidc_rawputchar(c);
- end_term();
+ vidc_text_set_cursor(row, col, true);
}
static void
-get_arg(int c)
+vidc_text_param(void *s __unused, int cmd, unsigned int value)
{
+ teken_unit_t row, col;
+
+ switch (cmd) {
+ case TP_SETLOCALCURSOR:
+ /*
+ * 0 means normal (usually block), 1 means hidden, and
+ * 2 means blinking (always block) for compatibility with
+ * syscons. We don't support any changes except hiding,
+ * so must map 2 to 0.
+ */
+ value = (value == 1) ? 0 : 1;
+ /* FALLTHROUGH */
+ case TP_SHOWCURSOR:
+ vidc_text_get_cursor(&row, &col);
+ if (value == 1)
+ vidc_text_set_cursor(row, col, true);
+ else
+ vidc_text_set_cursor(row, col, false);
+ break;
+ default:
+ /* Not yet implemented */
+ break;
+ }
+}
- if (argc < 0)
- argc = 0;
- args[argc] *= 10;
- args[argc] += c - '0';
+/*
+ * Not implemented.
+ */
+static void
+vidc_cons_respond(void *s __unused, const void *buf __unused,
+ size_t len __unused)
+{
}
-/* Emulate basic capabilities of cons25 terminal */
-void
-vidc_term_emu(int c)
+static void
+vidc_probe(struct console *cp)
{
- static int ansi_col[] = {
- 0, 4, 2, 6, 1, 5, 3, 7,
- };
- int t;
- int i;
-
- switch (esc) {
- case 0:
- switch (c) {
- case '\033':
- esc = c;
- break;
- default:
- vidc_rawputchar(c);
- break;
- }
- break;
-
- case '\033':
- switch (c) {
- case '[':
- esc = c;
- args[0] = 0;
- argc = -1;
- break;
- default:
- bail_out(c);
- break;
- }
- break;
-
- case '[':
- switch (c) {
- case ';':
- if (argc < 0) /* XXX */
- argc = 0;
- else if (argc + 1 >= MAXARGS)
- bail_out(c);
- else
- args[++argc] = 0;
- break;
- case 'H':
- if (argc < 0)
- HO();
- else if (argc == 1)
- CM();
- else
- bail_out(c);
- break;
- case 'J':
- if (argc < 0)
- CD();
- else
- bail_out(c);
- break;
- case 'm':
- if (argc < 0) {
- fg_c = DEFAULT_FGCOLOR;
- bg_c = DEFAULT_BGCOLOR;
- }
- for (i = 0; i <= argc; ++i) {
- switch (args[i]) {
- case 0: /* back to normal */
- fg_c = DEFAULT_FGCOLOR;
- bg_c = DEFAULT_BGCOLOR;
- break;
- case 1: /* bold */
- fg_c |= 0x8;
- break;
- case 4: /* underline */
- case 5: /* blink */
- bg_c |= 0x8;
- break;
- case 7: /* reverse */
- t = fg_c;
- fg_c = bg_c;
- bg_c = t;
- break;
- case 22: /* normal intensity */
- fg_c &= ~0x8;
- break;
- case 24: /* not underline */
- case 25: /* not blinking */
- bg_c &= ~0x8;
- break;
- case 30: case 31: case 32: case 33:
- case 34: case 35: case 36: case 37:
- fg_c = ansi_col[args[i] - 30];
- break;
- case 39: /* normal */
- fg_c = DEFAULT_FGCOLOR;
- break;
- case 40: case 41: case 42: case 43:
- case 44: case 45: case 46: case 47:
- bg_c = ansi_col[args[i] - 40];
- break;
- case 49: /* normal */
- bg_c = DEFAULT_BGCOLOR;
- break;
+
+ /* look for a keyboard */
+#if KEYBOARD_PROBE
+ if (probe_keyboard())
+#endif
+ {
+
+ cp->c_flags |= C_PRESENTIN;
+ }
+
+ /* XXX for now, always assume we can do BIOS screen output */
+ cp->c_flags |= C_PRESENTOUT;
+}
+
+static int
+vidc_init(int arg)
+{
+ const teken_attr_t *a;
+ int val;
+
+ if (vidc_started && arg == 0)
+ return (0);
+
+ vidc_started = 1;
+
+ /*
+ * Check Miscellaneous Output Register (Read at 3CCh, Write at 3C2h)
+ * for bit 1 (Input/Output Address Select), which means
+ * color/graphics adapter.
+ */
+ if (vga_get_reg(VGA_REG_BASE, VGA_GEN_MISC_OUTPUT_R) & VGA_GEN_MO_IOA)
+ vgatext = (uint16_t *)PTOV(VGA_TXT_BASE);
+ else
+ vgatext = (uint16_t *)PTOV(VGA_MEM_BASE + VGA_MEM_SIZE);
+
+ /* set 16bit colors */
+ val = vga_get_atr(VGA_REG_BASE, VGA_AC_MODE_CONTROL);
+ val &= ~VGA_AC_MC_BI;
+ val &= ~VGA_AC_MC_ELG;
+ vga_set_atr(VGA_REG_BASE, VGA_AC_MODE_CONTROL, val);
+
+ tp.tp_row = TEXT_ROWS;
+ tp.tp_col = TEXT_COLS;
+ buffer = malloc(tp.tp_row * tp.tp_col * sizeof(*buffer));
+ if (buffer == NULL)
+ return (1);
+
+ teken_init(&teken, &tf, NULL);
+ teken_set_winsize(&teken, &tp);
+ a = teken_get_defattr(&teken);
+
+ for (int row = 0; row < tp.tp_row; row++)
+ for (int col = 0; col < tp.tp_col; col++) {
+ buffer[col + row * tp.tp_col].c = ' ';
+ buffer[col + row * tp.tp_col].a = *a;
}
- }
- end_term();
- break;
- default:
- if (isdigit(c))
- get_arg(c);
- else
- bail_out(c);
- break;
- }
- break;
- default:
- bail_out(c);
- break;
- }
+ for (int i = 0; i < 10 && vidc_ischar(); i++)
+ (void) vidc_getchar();
+
+ return (0); /* XXX reinit? */
+}
+
+void
+vidc_biosputchar(int c)
+{
+
+ v86.ctl = 0;
+ v86.addr = 0x10;
+ v86.eax = 0xe00 | (c & 0xff);
+ v86.ebx = 0x7;
+ v86int();
}
-#endif
static void
vidc_putchar(int c)
{
-#ifdef TERM_EMU
- vidc_term_emu(c);
-#else
- vidc_rawputchar(c);
-#endif
+ unsigned char ch = c;
+
+ if (buffer != NULL)
+ teken_input(&teken, &ch, sizeof (ch));
+ else
+ vidc_biosputchar(c);
}
static int
vidc_getchar(void)
{
+ int i, c;
- if (vidc_ischar()) {
- v86.ctl = 0;
- v86.addr = 0x16;
- v86.eax = 0x0;
- v86int();
- return (v86.eax & 0xff);
- } else {
- return (-1);
- }
+ for (i = 0; i < KEYBUFSZ; i++) {
+ if (keybuf[i] != 0) {
+ c = keybuf[i];
+ keybuf[i] = 0;
+ return (c);
+ }
+ }
+
+ if (vidc_ischar()) {
+ v86.ctl = 0;
+ v86.addr = 0x16;
+ v86.eax = 0x0;
+ v86int();
+ if ((v86.eax & 0xff) != 0) {
+ return (v86.eax & 0xff);
+ }
+
+ /* extended keys */
+ switch (v86.eax & 0xff00) {
+ case 0x4800: /* up */
+ keybuf[0] = '[';
+ keybuf[1] = 'A';
+ return (0x1b); /* esc */
+ case 0x4b00: /* left */
+ keybuf[0] = '[';
+ keybuf[1] = 'D';
+ return (0x1b); /* esc */
+ case 0x4d00: /* right */
+ keybuf[0] = '[';
+ keybuf[1] = 'C';
+ return (0x1b); /* esc */
+ case 0x5000: /* down */
+ keybuf[0] = '[';
+ keybuf[1] = 'B';
+ return (0x1b); /* esc */
+ default:
+ return (-1);
+ }
+ } else {
+ return (-1);
+ }
}
static int
vidc_ischar(void)
{
+ int i;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x16;
- v86.eax = 0x100;
- v86int();
- return (!V86_ZR(v86.efl));
+ for (i = 0; i < KEYBUFSZ; i++) {
+ if (keybuf[i] != 0) {
+ return (1);
+ }
+ }
+
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x16;
+ v86.eax = 0x100;
+ v86int();
+ return (!V86_ZR(v86.efl));
}
#if KEYBOARD_PROBE
@@ -556,13 +728,13 @@ vidc_ischar(void)
static void
delay7(void)
{
- /*
- * I know this is broken, but no timer is available yet at this stage...
- * See also comments in `delay1ms()'.
- */
- inb(IO_DUMMY); inb(IO_DUMMY);
- inb(IO_DUMMY); inb(IO_DUMMY);
- inb(IO_DUMMY); inb(IO_DUMMY);
+ /*
+ * I know this is broken, but no timer is available yet at this stage...
+ * See also comments in `delay1ms()'.
+ */
+ inb(IO_DUMMY); inb(IO_DUMMY);
+ inb(IO_DUMMY); inb(IO_DUMMY);
+ inb(IO_DUMMY); inb(IO_DUMMY);
}
/*
@@ -577,9 +749,9 @@ delay7(void)
static void
delay1ms(void)
{
- int i = 800;
- while (--i >= 0)
- (void)inb(0x84);
+ int i = 800;
+ while (--i >= 0)
+ (void) inb(0x84);
}
/*
@@ -593,55 +765,57 @@ delay1ms(void)
static int
probe_keyboard(void)
{
- int retry = PROBE_MAXRETRY;
- int wait;
- int i;
-
- while (--retry >= 0) {
- /* flush any noise */
- while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
- delay7();
- inb(IO_KBD + KBD_DATA_PORT);
- delay1ms();
- }
-
- /* wait until the controller can accept a command */
- for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
- if (((i = inb(IO_KBD + KBD_STATUS_PORT))
- & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
- break;
- if (i & KBDS_ANY_BUFFER_FULL) {
- delay7();
- inb(IO_KBD + KBD_DATA_PORT);
- }
- delay1ms();
- }
- if (wait <= 0)
- continue;
-
- /* send the ECHO command */
- outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
+ int retry = PROBE_MAXRETRY;
+ int wait;
+ int i;
+
+ while (--retry >= 0) {
+ /* flush any noise */
+ while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
+ delay7();
+ inb(IO_KBD + KBD_DATA_PORT);
+ delay1ms();
+ }
- /* wait for a response */
- for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
- if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
- break;
- delay1ms();
- }
- if (wait <= 0)
- continue;
+ /* wait until the controller can accept a command */
+ for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
+ if (((i = inb(IO_KBD + KBD_STATUS_PORT))
+ & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL))
+ == 0)
+ break;
+ if (i & KBDS_ANY_BUFFER_FULL) {
+ delay7();
+ inb(IO_KBD + KBD_DATA_PORT);
+ }
+ delay1ms();
+ }
+ if (wait <= 0)
+ continue;
+
+ /* send the ECHO command */
+ outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
+
+ /* wait for a response */
+ for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
+ if (inb(IO_KBD + KBD_STATUS_PORT) &
+ KBDS_ANY_BUFFER_FULL)
+ break;
+ delay1ms();
+ }
+ if (wait <= 0)
+ continue;
- delay7();
- i = inb(IO_KBD + KBD_DATA_PORT);
+ delay7();
+ i = inb(IO_KBD + KBD_DATA_PORT);
#ifdef PROBE_KBD_BEBUG
- printf("probe_keyboard: got 0x%x.\n", i);
+ printf("probe_keyboard: got 0x%x.\n", i);
#endif
- if (i == KBD_ECHO) {
- /* got the right answer */
- return (1);
+ if (i == KBD_ECHO) {
+ /* got the right answer */
+ return (1);
+ }
}
- }
- return (0);
+ return (0);
}
#endif /* KEYBOARD_PROBE */