From 5bdaa65e7e48c7f8ab7a529bd4d3d08f2b24793c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 8 Oct 2015 16:29:58 +0100 Subject: [PATCH] vt: try and do something sane about vt and irq handling --- Kernel/vt.c | 84 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/Kernel/vt.c b/Kernel/vt.c index 2c6eb0b2..041793d9 100644 --- a/Kernel/vt.c +++ b/Kernel/vt.c @@ -60,6 +60,8 @@ uint8_t vtattr; static signed char cursorx; static signed char cursory = VT_INITIAL_LINE; static signed char ncursory; +static uint8_t vtpend; +static uint8_t vtbusy; static void cursor_fix(void) { @@ -175,35 +177,65 @@ static int escout(unsigned char c) /* VT52 alike functionality */ void vtoutput(unsigned char *p, unsigned int len) { + irqflags_t irq; + uint8_t cq; + + /* We can get re-entry into the vt code from tty echo. This is one of + the few places in Fuzix interrupts bite us this way. + + If we have a clash then we queue the echoed symbol and print it + in the thread of execution it interrupted. We only queue one so + in theory might lose the odd echo - but the same occurs with real + uarts. If anyone actually has printing code slow enough this is a + problem then vtpend can turn into a small queue */ + irq = di(); + if (vtbusy) { + vtpend = *p; + irqrestore(irq); + return; + } + vtbusy = 1; + irqrestore(irq); cursor_off(); - while (len--) { - unsigned char c = *p++; - if (vtmode == 0) { - charout(c); - continue; + do { + while (len--) { + unsigned char c = *p++; + if (vtmode == 0) { + charout(c); + continue; + } + if (vtmode == 1) { + vtmode = escout(c); + continue; + } + if (vtmode == 2) { + ncursory = c - ' '; + vtmode++; + continue; + } else if (vtmode == 3) { + int ncursorx = c - ' '; + if (ncursory >= 0 && ncursorx <= VT_BOTTOM) + cursory = ncursory; + if (ncursorx >= 0 && ncursorx <= VT_RIGHT) + cursorx = ncursorx; + vtmode = 0; + } else { + vtattr = c; + vtmode = 0; + continue; + } } - if (vtmode == 1) { - vtmode = escout(c); - continue; - } - if (vtmode == 2) { - ncursory = c - ' '; - vtmode++; - continue; - } else if (vtmode == 3) { - int ncursorx = c - ' '; - if (ncursory >= 0 && ncursorx <= VT_BOTTOM) - cursory = ncursory; - if (ncursorx >= 0 && ncursorx <= VT_RIGHT) - cursorx = ncursorx; - vtmode = 0; - } else { - vtattr = c; - vtmode = 0; - continue; - } - } + /* Copy the pending symbol and clear the buffer */ + cq = vtpend; + vtpend = 0; + /* Any loops print the single byte in cq */ + p = &cq; + len = 1; + /* Until we don't get interrupted */ + } while(cq); + cursor_on(cursory, cursorx); + vtbusy = 0; } int vt_ioctl(uint8_t minor, uarg_t request, char *data) -- 2.34.1