Use hardware-provided cursor on text-mode displays

This commit is contained in:
Mark
2020-07-03 11:19:24 +03:00
parent 014ff82396
commit dbf4f57913
4 changed files with 45 additions and 25 deletions
+11
View File
@@ -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);
+3 -1
View File
@@ -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;
+1
View File
@@ -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
+30 -24
View File
@@ -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) {