diff src/console.c @ 0:83c23a36980d

Init
author Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
date Fri, 26 May 2017 23:11:05 +0900
parents
children 36bd61f5c847
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/console.c	Fri May 26 23:11:05 2017 +0900
@@ -0,0 +1,294 @@
+// Console input and output.
+// Input is from the keyboard or serial port.
+// Output is written to the screen and serial port.
+
+#include "types.h"
+#include "defs.h"
+#include "param.h"
+#include "spinlock.h"
+#include "fs.h"
+#include "file.h"
+#include "memlayout.h"
+#include "mmu.h"
+#include "proc.h"
+
+static void consputc (int);
+
+static int panicked = 0;
+
+static struct {
+    struct spinlock lock;
+    int locking;
+} cons;
+
+static void printint (int xx, int base, int sign)
+{
+    static char digits[] = "0123456789abcdef";
+    char buf[16];
+    int i;
+    uint x;
+
+    if (sign && (sign = xx < 0)) {
+        x = -xx;
+    } else {
+        x = xx;
+    }
+
+    i = 0;
+
+    do {
+        buf[i++] = digits[x % base];
+    } while ((x /= base) != 0);
+
+    if (sign) {
+        buf[i++] = '-';
+    }
+
+    while (--i >= 0) {
+        consputc(buf[i]);
+    }
+}
+//PAGEBREAK: 50
+
+// Print to the console. only understands %d, %x, %p, %s.
+void cprintf (char *fmt, ...)
+{
+    int i, c, locking;
+    uint *argp;
+    char *s;
+
+    locking = cons.locking;
+
+    if (locking) {
+        acquire(&cons.lock);
+    }
+
+    if (fmt == 0) {
+        panic("null fmt");
+    }
+
+    argp = (uint*) (void*) (&fmt + 1);
+
+    for (i = 0; (c = fmt[i] & 0xff) != 0; i++) {
+        if (c != '%') {
+            consputc(c);
+            continue;
+        }
+
+        c = fmt[++i] & 0xff;
+
+        if (c == 0) {
+            break;
+        }
+
+        switch (c) {
+        case 'd':
+            printint(*argp++, 10, 1);
+            break;
+
+        case 'x':
+        case 'p':
+            printint(*argp++, 16, 0);
+            break;
+
+        case 's':
+            if ((s = (char*) *argp++) == 0) {
+                s = "(null)";
+            }
+
+            for (; *s; s++) {
+                consputc(*s);
+            }
+            break;
+
+        case '%':
+            consputc('%');
+            break;
+
+        default:
+            // Print unknown % sequence to draw attention.
+            consputc('%');
+            consputc(c);
+            break;
+        }
+    }
+
+    if (locking) {
+        release(&cons.lock);
+    }
+}
+
+void panic (char *s)
+{
+    cli();
+
+    cons.locking = 0;
+
+    cprintf("cpu%d: panic: ", cpu->id);
+
+    show_callstk(s);
+    panicked = 1; // freeze other CPU
+
+    while (1)
+        ;
+}
+
+//PAGEBREAK: 50
+#define BACKSPACE 0x100
+#define CRTPORT 0x3d4
+
+void consputc (int c)
+{
+    if (panicked) {
+        cli();
+        while (1)
+            ;
+    }
+
+    if (c == BACKSPACE) {
+        uartputc('\b');
+        uartputc(' ');
+        uartputc('\b');
+    } else {
+        uartputc(c);
+    }
+
+    // cgaputc(c);
+}
+
+#define INPUT_BUF 512
+struct {
+    struct spinlock lock;
+    char buf[INPUT_BUF];
+    uint r;  // Read index
+    uint w;  // Write index
+    uint e;  // Edit index
+} input;
+
+#define C(x)  ((x)-'@')  // Control-x
+void consoleintr (int (*getc) (void))
+{
+    int c;
+
+    acquire(&input.lock);
+
+    while ((c = getc()) >= 0) {
+        switch (c) {
+        case C('P'):  // Process listing.
+            procdump();
+            break;
+
+        case C('U'):  // Kill line.
+            while ((input.e != input.w) && (input.buf[(input.e - 1) % INPUT_BUF] != '\n')) {
+                input.e--;
+                consputc(BACKSPACE);
+            }
+
+            break;
+
+        case C('H'):
+        case '\x7f':  // Backspace
+            if (input.e != input.w) {
+                input.e--;
+                consputc(BACKSPACE);
+            }
+
+            break;
+
+        default:
+            if ((c != 0) && (input.e - input.r < INPUT_BUF)) {
+                c = (c == '\r') ? '\n' : c;
+
+                input.buf[input.e++ % INPUT_BUF] = c;
+                consputc(c);
+
+                if (c == '\n' || c == C('D') || input.e == input.r + INPUT_BUF) {
+                    input.w = input.e;
+                    wakeup(&input.r);
+                }
+            }
+
+            break;
+        }
+    }
+
+    release(&input.lock);
+}
+
+int consoleread (struct inode *ip, char *dst, int n)
+{
+    uint target;
+    int c;
+
+    iunlock(ip);
+
+    target = n;
+    acquire(&input.lock);
+
+    while (n > 0) {
+        while (input.r == input.w) {
+            if (proc->killed) {
+                release(&input.lock);
+                ilock(ip);
+                return -1;
+            }
+
+            sleep(&input.r, &input.lock);
+        }
+
+        c = input.buf[input.r++ % INPUT_BUF];
+
+        if (c == C('D')) {  // EOF
+            if (n < target) {
+                // Save ^D for next time, to make sure
+                // caller gets a 0-byte result.
+                input.r--;
+            }
+
+            break;
+        }
+
+        *dst++ = c;
+        --n;
+
+        if (c == '\n') {
+            break;
+        }
+    }
+
+    release(&input.lock);
+    ilock(ip);
+
+    return target - n;
+}
+
+int consolewrite (struct inode *ip, char *buf, int n)
+{
+    int i;
+
+    iunlock(ip);
+
+    acquire(&cons.lock);
+
+    for (i = 0; i < n; i++) {
+        consputc(buf[i] & 0xff);
+    }
+
+    release(&cons.lock);
+
+    ilock(ip);
+
+    return n;
+}
+
+void consoleinit (void)
+{
+    initlock(&cons.lock, "console");
+    initlock(&input.lock, "input");
+
+    devsw[CONSOLE].write = consolewrite;
+    devsw[CONSOLE].read = consoleread;
+
+    cons.locking = 1;
+}
+