summaryrefslogtreecommitdiff
path: root/kernel/con.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/con.c')
-rw-r--r--kernel/con.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/kernel/con.c b/kernel/con.c
new file mode 100644
index 0000000..b3d2b9d
--- /dev/null
+++ b/kernel/con.c
@@ -0,0 +1,96 @@
+/*
+ * con.c
+ *
+ * Basic VGA text console
+ */
+
+#include <asm/io.h>
+#include <kernel/vsprintf.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#define COLS 80
+#define ROWS 25
+
+static uint8_t *vram = (uint8_t*) 0xB8000;
+static int pos;
+
+static inline void cursorpos(int pos) {
+ outb(0x3D4, 0x0E);
+ outb(0x3D5, (uint8_t) ((pos >> 9) & 0xFF));
+ outb(0x3D4, 0x0F);
+ outb(0x3D5, (uint8_t) ((pos >> 1) & 0xFF));
+}
+
+/* scrolls the console up one line */
+static void scroll_up(void) {
+ int n = (COLS * (ROWS - 1)) << 1;
+ uint8_t *p = vram;
+
+ while(n--) {
+ *p = p[COLS << 1];
+ p++;
+ }
+
+ p = (uint8_t*) (vram + (COLS * (ROWS - 1) << 1));
+ n = COLS;
+ while(n--) {
+ *p = ' ';
+ p += 2;
+ }
+
+ pos -= COLS << 1;
+ cursorpos(pos);
+}
+
+/* must be called before any console output */
+void con_init(void) {
+ int n = COLS * ROWS;
+ uint8_t *p = vram;
+
+ while(n--) {
+ *(p++) = 0x20;
+ *(p++) = 0x07;
+ }
+
+ pos = 0;
+ cursorpos(0);
+}
+
+/* write a zero-terminated string to console */
+void con_print(char *s) {
+ uint8_t *p = &vram[pos];
+
+ while(*s) {
+ if(*s == '\n') {
+ pos = (int) (p - vram);
+ pos = ((pos / (COLS << 1)) + 1) * (COLS << 1);
+ p = &vram[pos];
+ s++;
+ } else {
+ *p = *(s++);
+ p += 2;
+ }
+
+ pos = (int) (p - vram);
+
+ if(pos >= (COLS * ROWS) << 1)
+ scroll_up();
+ }
+
+ /* update the cursor position */
+ cursorpos(pos);
+}
+
+int printf(char *fmt, ...) {
+ int ret;
+ char buf[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ con_print(buf);
+ return ret;
+}