summaryrefslogtreecommitdiff
path: root/sys/dev/cons/cons.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/cons/cons.c')
-rw-r--r--sys/dev/cons/cons.c214
1 files changed, 153 insertions, 61 deletions
diff --git a/sys/dev/cons/cons.c b/sys/dev/cons/cons.c
index b89727f..8470a60 100644
--- a/sys/dev/cons/cons.c
+++ b/sys/dev/cons/cons.c
@@ -44,7 +44,7 @@
cons_draw_cursor((SCR), (SCR)->bg)
#define SHOW_CURSOR(SCR) \
- cons_draw_cursor((SCR), (SCR)->fg)
+ cons_draw_cursor((SCR), rgb_invert((SCR)->bg))
/* Console background from kconf */
#if defined(__CONSOLE_BG)
@@ -65,7 +65,23 @@ static struct cdevsw cons_cdevsw;
static void cons_draw_cursor(struct cons_screen *scr, uint32_t color);
static int cons_handle_special(struct cons_screen *scr, char c);
-static void cons_clear_scr(struct cons_screen *scr, uint32_t bg);
+
+static uint32_t
+rgb_invert(uint32_t rgb)
+{
+ uint8_t r, g, b;
+ uint32_t ret;
+
+ r = (rgb >> 16) & 0xFF;
+ g = (rgb >> 8) & 0xFF;
+ b = rgb & 0xFF;
+
+ ret = (255 - r) << 16;
+ ret |= (255 - g) << 8;
+ ret |= 255 - b;
+ return ret;
+}
+
/*
* Render a character onto the screen.
@@ -91,9 +107,9 @@ cons_draw_char(struct cons_screen *scr, struct cons_char ch)
y = ch.y;
for (uint32_t cy = 0; cy < FONT_HEIGHT; ++cy) {
+ idx = fbdev_get_index(&scr->fbdev, x + (FONT_WIDTH - 1), y + cy);
for (uint32_t cx = 0; cx < FONT_WIDTH; ++cx) {
- idx = fbdev_get_index(&scr->fbdev, x + (FONT_WIDTH - 1) - cx, y + cy);
- scr->fb_mem[idx] = ISSET(glyph[cy], BIT(cx)) ? ch.fg : ch.bg;
+ scr->fb_mem[idx--] = ISSET(glyph[cy], BIT(cx)) ? ch.fg : ch.bg;
}
}
}
@@ -158,6 +174,17 @@ cons_handle_special(struct cons_screen *scr, char c)
}
switch (c) {
+ case ASCII_HT:
+ HIDE_CURSOR(scr);
+ scr->curs_col += 4;
+ scr->ch_col += 4;
+ if (scr->ch_col >= scr->ncols - 1) {
+ cons_handle_special(scr, '\n');
+ }
+ SHOW_CURSOR(scr);
+ return 0;
+ case ASCII_NUL:
+ return 0;
case ASCII_BS:
bp = scr->ob[scr->ch_row];
if (bp->head > bp->tail) {
@@ -165,27 +192,21 @@ cons_handle_special(struct cons_screen *scr, char c)
}
HIDE_CURSOR(scr);
- --scr->ch_col;
- --scr->curs_col;
+ if (scr->ch_col > 0 && scr->curs_col > 0) {
+ --scr->ch_col;
+ --scr->curs_col;
+ }
SHOW_CURSOR(scr);
return 0;
case ASCII_LF:
- HIDE_CURSOR(scr);
-
/* Are we past screen width? */
if (scr->ch_row >= scr->nrows - 1) {
cons_clear_scr(scr, scr->bg);
- cons_flush(scr);
- scr->ch_col = 0;
- scr->ch_row = 0;
-
- /* Update cursor */
- scr->curs_row = 0;
- scr->curs_col = 0;
- SHOW_CURSOR(scr);
return 0;
}
+ HIDE_CURSOR(scr);
+
/* Make a newline */
cons_flush(scr);
++scr->ch_row;
@@ -221,9 +242,9 @@ cons_draw_cursor(struct cons_screen *scr, uint32_t color)
}
for (uint32_t cy = 0; cy < FONT_HEIGHT; ++cy) {
+ idx = fbdev_get_index(&scr->fbdev, scr->curs_col * FONT_WIDTH, (scr->curs_row * FONT_HEIGHT) + cy);
for (uint32_t cx = 0; cx < FONT_WIDTH; ++cx) {
- idx = fbdev_get_index(&scr->fbdev, (scr->curs_col * FONT_WIDTH) + cx, (scr->curs_row * FONT_HEIGHT) + cy);
- scr->fb_mem[idx] = color;
+ scr->fb_mem[idx++] = color;
}
}
}
@@ -234,34 +255,87 @@ cons_draw_cursor(struct cons_screen *scr, uint32_t color)
* @scr: Screen to clear.
* @bg: Color to clear it to.
*/
-static void
+void
cons_clear_scr(struct cons_screen *scr, uint32_t bg)
{
struct fbdev fbdev = scr->fbdev;
- struct cons_buf *bp;
+
+ cons_flush(scr);
+ HIDE_CURSOR(scr);
+
+ scr->ch_col = 0;
+ scr->ch_row = 0;
+ scr->curs_col = 0;
+ scr->curs_row = 0;
for (size_t i = 0; i < fbdev.height * fbdev.pitch; ++i) {
scr->fb_mem[i] = bg;
}
- bp = scr->ob[scr->nrows - 1];
- bp->flags |= CONS_BUF_CLEAN;
+ SHOW_CURSOR(scr);
+
}
/*
- * Character device function.
+ * Quickly put a character on the screen.
+ * XXX: Does not acquire the screen's lock or show/hide the cursor.
+ *
+ * @scr: Screen.
+ * @c: Character to draw.
*/
-static int
-dev_write(dev_t dev, struct sio_txn *sio, int flags)
+static void
+cons_fast_putch(struct cons_screen *scr, char c)
{
- char *p;
+ struct cons_char cc;
+ struct cons_buf *bp;
+ int ansi;
+
+ ansi = ansi_feed(&scr->ansi_s, c);
+ if (ansi > 0) {
+ c = ASCII_NUL;
+ } else if (ansi < 0) {
+ c = ASCII_NUL;
+ }
+
+ /* Handle specials */
+ if (cons_handle_special(scr, c) == 0) {
+ return;
+ }
+
+ /* Create a new character */
+ cc.c = c;
+ cc.fg = scr->fg;
+ cc.bg = scr->bg;
+ cc.x = scr->ch_col * FONT_WIDTH;
+ cc.y = scr->ch_row * FONT_HEIGHT;
+
+ /* Push our new character */
+ bp = scr->ob[scr->ch_row];
+ bp->flags &= ~CONS_BUF_CLEAN;
+ cons_obuf_push(bp, cc);
+ ++scr->ch_col;
- p = sio->buf;
+ /* Check screen bounds */
+ if (cc.x >= (scr->ncols * FONT_WIDTH) - 1) {
+ scr->ch_col = 0;
+ ++scr->ch_row;
+ }
- for (size_t i = 0; i < sio->len; ++i) {
- cons_putch(&g_root_scr, p[i]);
+ ++scr->curs_col;
+ if (scr->curs_col > scr->ncols - 1) {
+ scr->curs_col = 0;
+ if (scr->curs_row < scr->nrows)
+ ++scr->curs_row;
}
+}
+/*
+ * Character device function.
+ */
+static int
+dev_write(dev_t dev, struct sio_txn *sio, int flags)
+{
+ cons_putstr(&g_root_scr, sio->buf, sio->len);
cons_flush(&g_root_scr);
return sio->len;
}
@@ -339,6 +413,34 @@ cons_init_bufs(struct cons_screen *scr)
}
/*
+ * Reset console color.
+ */
+void
+cons_reset_color(struct cons_screen *scr)
+{
+ g_root_scr.fg = CONSOLE_FG;
+ g_root_scr.bg = CONSOLE_BG;
+}
+
+void
+cons_update_color(struct cons_screen *scr, uint32_t fg, uint32_t bg)
+{
+ scr->fg = fg;
+ scr->bg = bg;
+}
+
+void
+cons_reset_cursor(struct cons_screen *scr)
+{
+ HIDE_CURSOR(scr);
+ scr->ch_col = 0;
+ scr->ch_row = 0;
+ scr->curs_col = 0;
+ scr->curs_row = 0;
+ SHOW_CURSOR(scr);
+}
+
+/*
* Put a character on the screen.
*
* @scr: Screen.
@@ -347,47 +449,37 @@ cons_init_bufs(struct cons_screen *scr)
int
cons_putch(struct cons_screen *scr, char c)
{
- struct cons_buf *bp;
- struct cons_char cc;
- size_t max_width;
-
spinlock_acquire(&scr->lock);
+ HIDE_CURSOR(scr);
- /* Handle specials */
- if (cons_handle_special(scr, c) == 0) {
- goto done;
- }
+ cons_fast_putch(scr, c);
- HIDE_CURSOR(scr);
+ SHOW_CURSOR(scr);
+ spinlock_release(&scr->lock);
+ return 0;
+}
- /* Create a new character */
- cc.c = c;
- cc.fg = scr->fg;
- cc.bg = scr->bg;
- cc.x = scr->ch_col * FONT_WIDTH;
- cc.y = scr->ch_row * FONT_HEIGHT;
+/*
+ * Put a string on the screen.
+ *
+ * @scr: Screen.
+ * @s: String to draw.
+ * @l: Length of s.
+ */
+int
+cons_putstr(struct cons_screen *scr, const char *s, size_t len)
+{
+ const char *p = s;
- /* Push our new character */
- bp = scr->ob[scr->ch_row];
- bp->flags &= ~CONS_BUF_CLEAN;
- cons_obuf_push(bp, cc);
- ++scr->ch_col;
+ spinlock_acquire(&scr->lock);
+ HIDE_CURSOR(scr);
- /* Check screen bounds */
- max_width = scr->ncols * FONT_WIDTH;
- if (cc.x >= max_width - 1) {
- scr->ch_col = 0;
- ++scr->ch_row;
+ while (len--) {
+ cons_fast_putch(scr, *p);
+ ++p;
}
- ++scr->curs_col;
- if (scr->curs_col > scr->ncols - 1) {
- scr->curs_col = 0;
- if (scr->curs_row < scr->nrows)
- ++scr->curs_row;
- }
SHOW_CURSOR(scr);
-done:
spinlock_release(&scr->lock);
return 0;
}