Use hardware-provided cursor on text-mode displays
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user