# HG changeset patch # User John Tsiombikas # Date 1291442683 -7200 # Node ID 86781ef20689fa92468d486c7e134da787b964a9 # Parent ebe5e0e44a9d727332c27752f74dfd1b628e2392 added hardware scrolling, memset16 and temporary keyboard input for testing diff -r ebe5e0e44a9d -r 86781ef20689 Makefile --- a/Makefile Thu Dec 02 08:45:41 2010 +0200 +++ b/Makefile Sat Dec 04 08:04:43 2010 +0200 @@ -3,7 +3,7 @@ asmsrc = $(wildcard src/*.S) $(wildcard src/klibc/*.S) # each source file will generate one object file -obj = $(csrc:.c=.o) $(asmsrc:.S=.o) +obj = $(asmsrc:.S=.o) $(csrc:.c=.o) CC = gcc diff -r ebe5e0e44a9d -r 86781ef20689 src/asmops.h --- a/src/asmops.h Thu Dec 02 08:45:41 2010 +0200 +++ b/src/asmops.h Sat Dec 04 08:04:43 2010 +0200 @@ -3,29 +3,29 @@ #define inb(dest, port) asm volatile( \ "inb %1, %0\n\t" \ - : "=a" (unsigned char)(dest) \ - : "dN" (unsigned short)(port)) + : "=a" ((unsigned char)(dest)) \ + : "dN" ((unsigned short)(port))) #define ins(dest, port) asm volatile( \ "ins %1, %0\n\t" \ - : "=a" (unsigned short)(dest) \ - : "dN" (unsigned short)(port)) + : "=a" ((unsigned short)(dest)) \ + : "dN" ((unsigned short)(port))) #define inl(dest, port) asm volatile( \ "inl %1, %0\n\t" \ - : "=a" (unsigned long)(dest) \ - : "dN" (unsigned short)(port)) + : "=a" ((unsigned long)(dest)) \ + : "dN" ((unsigned short)(port))) #define outb(src, port) asm volatile( \ "outb %0, %1\n\t" \ - :: "a" (unsigned char)(src), "dN" (unsigned short)(port)) + :: "a" ((unsigned char)(src)), "dN" ((unsigned short)(port))) #define outs(src, port) asm volatile( \ "outs %0, %1\n\t" \ - :: "a" (unsigned short)(src), "dN" (unsigned short)(port)) + :: "a" ((unsigned short)(src)), "dN" ((unsigned short)(port))) #define outl(src, port) asm volatile( \ "outl %0, %1\n\t" \ - :: "a" (unsigned long)(src), "dN" (unsigned short)(port)) + :: "a" ((unsigned long)(src)), "dN" ((unsigned short)(port))) #endif /* ASMOPS_H_ */ diff -r ebe5e0e44a9d -r 86781ef20689 src/klibc/ctype.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/klibc/ctype.c Sat Dec 04 08:04:43 2010 +0200 @@ -0,0 +1,56 @@ +#include "ctype.h" + +int isalnum(int c) +{ + return isalpha(c) || isdigit(c); +} + +int isalpha(int c) +{ + return isupper(c) || islower(c); +} + +int isblank(int c) +{ + return c == ' ' || c == '\t'; +} + +int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +int isupper(int c) +{ + return c >= 'A' && c <= 'Z'; +} + +int islower(int c) +{ + return c >= 'a' && c <= 'z'; +} + +int isgraph(int c) +{ + return c > ' ' && c <= '~'; +} + +int isprint(int c) +{ + return isgraph(c) || c == ' '; +} + +int isspace(int c) +{ + return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v'; +} + +int toupper(int c) +{ + return islower(c) ? (c + ('A' - 'a')) : c; +} + +int tolower(int c) +{ + return isupper(c) ? (c + ('A' - 'a')) : c; +} diff -r ebe5e0e44a9d -r 86781ef20689 src/klibc/ctype.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/klibc/ctype.h Sat Dec 04 08:04:43 2010 +0200 @@ -0,0 +1,17 @@ +#ifndef CTYPE_H_ +#define CTYPE_H_ + +int isalnum(int c); +int isalpha(int c); +#define isascii(c) ((c) < 128) +int isblank(int c); +int isdigit(int c); +int isupper(int c); +int islower(int c); +int isprint(int c); +int isspace(int c); + +int toupper(int c); +int tolower(int c); + +#endif /* CTYPE_H_ */ diff -r ebe5e0e44a9d -r 86781ef20689 src/klibc/stdio.c --- a/src/klibc/stdio.c Thu Dec 02 08:45:41 2010 +0200 +++ b/src/klibc/stdio.c Sat Dec 04 08:04:43 2010 +0200 @@ -7,5 +7,6 @@ while(*s) { putchar(*s++); } + putchar('\n'); return 0; } diff -r ebe5e0e44a9d -r 86781ef20689 src/klibc/string.c --- a/src/klibc/string.c Thu Dec 02 08:45:41 2010 +0200 +++ b/src/klibc/string.c Sat Dec 04 08:04:43 2010 +0200 @@ -8,6 +8,14 @@ } } +void memset16(void *s, int c, size_t n) +{ + short *ptr = s; + while(n--) { + *ptr++ = c; + } +} + void *memcpy(void *dest, const void *src, size_t n) { char *dptr = dest; diff -r ebe5e0e44a9d -r 86781ef20689 src/klibc/string.h --- a/src/klibc/string.h Thu Dec 02 08:45:41 2010 +0200 +++ b/src/klibc/string.h Sat Dec 04 08:04:43 2010 +0200 @@ -4,6 +4,8 @@ #include void memset(void *s, int c, size_t n); +void memset16(void *s, int c, size_t n); + void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n); diff -r ebe5e0e44a9d -r 86781ef20689 src/main.c --- a/src/main.c Thu Dec 02 08:45:41 2010 +0200 +++ b/src/main.c Sat Dec 04 08:04:43 2010 +0200 @@ -1,10 +1,55 @@ #include #include "vid.h" #include "term.h" +#include + +/* special keys */ +enum { + LALT, RALT, + LCTRL, RCTRL, + LSHIFT, RSHIFT, + F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, + CAPSLK, NUMLK, SCRLK, SYSRQ, + ESC = 27, + INSERT, DEL, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN, + NUM_DOT, NUM_ENTER, NUM_PLUS, NUM_MINUS, NUM_MUL, NUM_DIV, + NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, + BACKSP = 127 +}; + +/* table with rough translations from set 1 scancodes to ASCII-ish */ +static int keycodes[] = { + 0, ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* 0 - e */ + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* f - 1c */ + LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', /* 1d - 29 */ + LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', RSHIFT, /* 2a - 36 */ + NUM_MUL, LALT, ' ', CAPSLK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, /* 37 - 44 */ + NUMLK, SCRLK, NUM_7, NUM_8, NUM_9, NUM_MINUS, NUM_4, NUM_5, NUM_6, NUM_PLUS, /* 45 - 4e */ + NUM_1, NUM_2, NUM_3, NUM_0, NUM_DOT, SYSRQ, 0, 0, F11, F12, /* 4d - 58 */ + 0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ +}; + void kmain(void) { - clear_scr(0); - set_text_color(LTRED); + clear_scr(); + puts("kernel starting up"); + + set_text_color(YELLOW); + puts(""); + set_text_color(LTGRAY); puts("hello world!"); + + for(;;) { + char c, keypress; + do { + inb(keypress, 0x64); + } while(!(keypress & 1)); + inb(c, 0x60); + if(!(c & 0x80)) { + putchar(keycodes[c]); + } + } } diff -r ebe5e0e44a9d -r 86781ef20689 src/term.c --- a/src/term.c Thu Dec 02 08:45:41 2010 +0200 +++ b/src/term.c Sat Dec 04 08:04:43 2010 +0200 @@ -1,23 +1,35 @@ #include "term.h" #include "vid.h" -static int bg, fg = 15; +static int bg, fg = LTGRAY; static int cursor_x, cursor_y; -void set_text_color(int c) +/* sets the active text color and returns previous value */ +int set_text_color(int c) { + int prev = fg; + if(c >= 0 && c < 16) { fg = c; } + return prev; } -void set_back_color(int c) +/* sets the active background color and returns the current value */ +int set_back_color(int c) { + int prev = bg; + if(c >= 0 && c < 16) { bg = c; } + return prev; } +/* output a single character, handles formatting, cursor advancement + * and scrolling the screen when we reach the bottom. + * TODO make visible cursor actually move. + */ int putchar(int c) { switch(c) { @@ -38,10 +50,12 @@ break; default: - set_char(c, cursor_x, cursor_y, fg, bg); - if(++cursor_x >= WIDTH) { - cursor_x = 0; - cursor_y++; + if(isprint(c)) { + set_char(c, cursor_x, cursor_y, fg, bg); + if(++cursor_x >= WIDTH) { + cursor_x = 0; + cursor_y++; + } } } @@ -49,5 +63,7 @@ scroll_scr(); cursor_y--; } + + set_cursor(cursor_x, cursor_y); return c; } diff -r ebe5e0e44a9d -r 86781ef20689 src/term.h --- a/src/term.h Thu Dec 02 08:45:41 2010 +0200 +++ b/src/term.h Sat Dec 04 08:04:43 2010 +0200 @@ -1,8 +1,8 @@ #ifndef TERM_H_ #define TERM_H_ -void set_text_color(int c); -void set_back_color(int c); +int set_text_color(int c); +int set_back_color(int c); int putchar(int c); diff -r ebe5e0e44a9d -r 86781ef20689 src/vid.c --- a/src/vid.c Thu Dec 02 08:45:41 2010 +0200 +++ b/src/vid.c Sat Dec 04 08:04:43 2010 +0200 @@ -1,24 +1,145 @@ +#if 0 + #include #include "vid.h" +#include "asmops.h" + +/* height of our virtual console text buffer */ +#define VIRT_HEIGHT 1024 + +/* CRTC ports */ +#define CRTC_ADDR 0x3d4 +#define CRTC_DATA 0x3d5 + +/* CRTC registers */ +#define CRTC_START_HIGH 0xc +#define CRTC_START_LOW 0xd +#define CRTC_CURSOR_HIGH 0xe +#define CRTC_CURSOR_LOW 0xf + +/* construct a character with its attributes */ +#define VMEM_CHAR(c, fg, bg) \ + ((uint16_t)(c) | (((uint16_t)(fg) & 0xf) << 8) | (((uint16_t)(bg) & 0xf) << 12)) + +static void set_start_line(int line); static uint16_t *vmem = (uint16_t*)0xb8000; +static int start_line; -void clear_scr(int color) + +void clear_scr(void) { - memset(vmem, 0, WIDTH * HEIGHT * 2); + memset16(vmem, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH * HEIGHT); + start_line = 0; + set_start_line(0); + set_cursor(0, 0); } void set_char(char c, int x, int y, int fg, int bg) { - uint16_t attr = (fg & 0xf) | ((bg & 7) << 4); - vmem[y * WIDTH + x] = (uint16_t)c | (attr << 8); + vmem[(y + start_line) * WIDTH + x] = VMEM_CHAR(c, fg, bg); +} + +void set_cursor(int x, int y) +{ + int loc; + + if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) { + loc = 0xffff; + } else { + loc = (y + start_line) * WIDTH + x; + } + + outb(CRTC_CURSOR_LOW, CRTC_ADDR); + outb(loc, CRTC_DATA); + outb(CRTC_CURSOR_HIGH, CRTC_ADDR); + outb(loc >> 8, CRTC_DATA); } void scroll_scr(void) { - /* copy the second up to last text line, one line back, then - * clear the last line. - */ - memmove(vmem, vmem + WIDTH, WIDTH * (HEIGHT - 1) * 2); - memset(vmem + WIDTH * (HEIGHT -1), 0, WIDTH * 2); + if(++start_line > VIRT_HEIGHT - HEIGHT) { + /* The bottom of the visible range reached the end of our text buffer. + * Copy the rest of the lines to the top and reset start_line. + */ + memcpy(vmem, vmem + start_line * WIDTH, (HEIGHT - 1) * WIDTH); + start_line = 0; + } + + /* clear the next line that will be revealed by scrolling */ + int new_line = start_line + HEIGHT - 1; + memset16(vmem + new_line * WIDTH, VMEM_CHAR(' ', LTGRAY, BLACK), WIDTH); + + set_start_line(start_line); } + +static void set_start_line(int line) +{ + int start_addr = line * WIDTH; + + outb(CRTC_START_LOW, CRTC_ADDR); + outb(start_addr & 0xff, CRTC_DATA); + outb(CRTC_START_HIGH, CRTC_ADDR); + outb((start_addr >> 8) & 0xff, CRTC_DATA); +} +#endif /* 0 */ + +#include +#include "vid.h" +#include "asmops.h" + +#define WIDTH 80 +#define HEIGHT 25 + +/* CRTC ports */ +#define CRTC_ADDR 0x3d4 +#define CRTC_DATA 0x3d5 + +/* CRTC registers */ +#define CRTC_CURSOR_HIGH 0xe +#define CRTC_CURSOR_LOW 0xf + +/* construct a character with its attributes */ +#define VMEM_CHAR(c, fg, bg) \ + ((uint16_t)(c) | (((uint16_t)(fg) & 0xf) << 8) | \ + (((uint16_t)(bg) & 0xf) << 12)) + +#define CLEAR_CHAR VMEM_CHAR(' ', LTGRAY, BLACK) + +/* pointer to the text mode video memory */ +static uint16_t *vmem = (uint16_t*)0xb8000; + +void clear_scr(void) +{ + memset16(vmem, CLEAR_CHAR, WIDTH * HEIGHT); +} + +void set_char(char c, int x, int y, int fg, int bg) +{ + vmem[y * WIDTH + x] = VMEM_CHAR(c, fg, bg); +} + +void set_cursor(int x, int y) +{ + int loc; + if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) { + loc = 0xffff; + } else { + loc = y * WIDTH + x; + } + + /* tell the vga where we want the cursor by writing + * to the "cursor address" register of the CRTC */ + outb(CRTC_CURSOR_LOW, CRTC_ADDR); + outb(loc, CRTC_DATA); + outb(CRTC_CURSOR_HIGH, CRTC_ADDR); + outb(loc >> 8, CRTC_DATA); +} + +void scroll_scr(void) +{ + /* simple scrolling by manually copying memory */ + memmove(vmem, vmem + WIDTH, WIDTH * (HEIGHT - 1) * 2); + memset16(vmem + WIDTH * (HEIGHT - 1), CLEAR_CHAR, WIDTH); +} + diff -r ebe5e0e44a9d -r 86781ef20689 src/vid.h --- a/src/vid.h Thu Dec 02 08:45:41 2010 +0200 +++ b/src/vid.h Sat Dec 04 08:04:43 2010 +0200 @@ -1,9 +1,10 @@ #ifndef VID_H_ #define VID_H_ -#define WIDTH 80 -#define HEIGHT 25 +#define WIDTH 80 +#define HEIGHT 25 +/* the standard CGA color palette */ enum { BLACK, BLUE, @@ -23,8 +24,9 @@ WHITE }; -void clear_scr(int color); +void clear_scr(void); void set_char(char c, int x, int y, int fg, int bg); +void set_cursor(int x, int y); void scroll_scr(void); #endif /* VID_H_ */