From dbf4f57913f71de7de3a27aa2d2a2da9416ffc9b Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 3 Jul 2020 11:19:24 +0300 Subject: [PATCH] Use hardware-provided cursor on text-mode displays --- arch/amd64/hw/con.c | 11 +++++++++ arch/amd64/hw/timer.c | 4 +++- include/sys/display.h | 1 + sys/console.c | 54 ++++++++++++++++++++++++------------------- 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/arch/amd64/hw/con.c b/arch/amd64/hw/con.c index 497c07c..5b8f2e0 100644 --- a/arch/amd64/hw/con.c +++ b/arch/amd64/hw/con.c @@ -1,4 +1,5 @@ #include "arch/amd64/hw/con.h" +#include "arch/amd64/hw/io.h" #include "sys/display.h" #define BUFFER ((uint16_t volatile*) 0xFFFFFF00000B8000) @@ -9,11 +10,21 @@ static void amd64_console_setc(uint16_t y, uint16_t x, uint16_t c) { BUFFER[y * 80 + x] = c; } +static void amd64_console_cursor(uint16_t y, uint16_t x) { + uint16_t pos = y * 80 + x; + + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); +} + void amd64_console_init(void) { display_console.flags = 0; display_console.width_chars = 80; display_console.height_chars = 25; display_console.setc = amd64_console_setc; + display_console.cursor = amd64_console_cursor; list_head_init(&display_console.list); display_add(&display_console); diff --git a/arch/amd64/hw/timer.c b/arch/amd64/hw/timer.c index 618d2ed..c1cfe82 100644 --- a/arch/amd64/hw/timer.c +++ b/arch/amd64/hw/timer.c @@ -65,7 +65,9 @@ static uint32_t timer_tick(void *arg) { g_display_blink_state ^= 1; int_timer_ticks = 0; } - console_update_cursor(); + if (int_timer_ticks % 2 == 0) { + console_update_cursor(); + } // Each tick is approx. 1ms, so add 1ms to system time system_time += 1000000; break; diff --git a/include/sys/display.h b/include/sys/display.h index 13f319b..dab973a 100644 --- a/include/sys/display.h +++ b/include/sys/display.h @@ -10,6 +10,7 @@ struct display { // Text modes: set character at y, x void (*setc) (uint16_t y, uint16_t x, uint16_t c); + void (*cursor) (uint16_t y, uint16_t x); uint32_t flags; // If DISP_GRAPHIC diff --git a/sys/console.c b/sys/console.c index bcbb06a..157419a 100644 --- a/sys/console.c +++ b/sys/console.c @@ -303,34 +303,40 @@ void console_update_cursor(void) { struct console *con; static int prev_blink = 0; - if (g_display_blink_state != prev_blink) { - list_for_each_entry(con, &g_consoles, list) { - if (con->display && con->buf_active) { - // TODO: don't blink on text-mode only consoles: - // use hardware cursor - struct console_buffer *buf = con->buf_active; - uint16_t c = buf->data[buf->y * con->width_chars + buf->x]; - if (g_display_blink_state) { - // Swap attributes - c = ((c >> 4) & 0xF00) | - ((c & 0xF00) << 4) | - (c & 0xFF); - } - display_setc(con->display, buf->y, buf->x, c); - if (buf->last_blink_x != buf->x || buf->last_blink_y != buf->y) { - // Also redraw character at last blink position - display_setc(con->display, - buf->last_blink_y, - buf->last_blink_x, - buf->data[buf->last_blink_y * con->width_chars + - buf->last_blink_x]); - buf->last_blink_x = buf->x; - buf->last_blink_y = buf->y; + list_for_each_entry(con, &g_consoles, list) { + if (con->display && con->buf_active) { + struct display *d = con->display; + struct console_buffer *buf = con->buf_active; + + if (d->flags & DISP_GRAPHIC) { + if (g_display_blink_state != prev_blink) { + uint16_t c = buf->data[buf->y * con->width_chars + buf->x]; + if (g_display_blink_state) { + // Swap attributes + c = ((c >> 4) & 0xF00) | + ((c & 0xF00) << 4) | + (c & 0xFF); + } + display_setc(d, buf->y, buf->x, c); + if (buf->last_blink_x != buf->x || buf->last_blink_y != buf->y) { + // Also redraw character at last blink position + display_setc(d, + buf->last_blink_y, + buf->last_blink_x, + buf->data[buf->last_blink_y * con->width_chars + + buf->last_blink_x]); + buf->last_blink_x = buf->x; + buf->last_blink_y = buf->y; + } } + } else { + _assert(d->cursor); + d->cursor(buf->y, buf->x); } } - prev_blink = g_display_blink_state; } + + prev_blink = g_display_blink_state; } void console_putc(struct console *con, struct chrdev *tty, int c) {