From d2aebee488b71e6f28b8728e7473b63f412ca897 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Thu, 11 Jul 2013 22:38:20 +0200 Subject: Added direct acces to video memory from userland. Next : same for keyboard ; move VT handling to userland. Consequence : a foreground app has total control over I/O. Next : implement sockets & a userland console multiplexer. --- doc/vfs.txt | 30 ++++++++++++++++++++++++-- src/include/tce/syscalls.h | 1 + src/include/tce/vfs.h | 7 ++++-- src/kernel/dev/display.h | 1 - src/kernel/dev/keyboard.cpp | 2 +- src/kernel/dev/ps2keyboard.cpp | 1 + src/kernel/dev/vgatxt.cpp | 34 +++++++++++++++++++++++++++++- src/kernel/dev/vgatxt.h | 7 ++++++ src/kernel/mem/paging.cpp | 1 + src/kernel/task/syscall.cpp | 5 +++++ src/kernel/vfs/node.cpp | 6 ++++++ src/kernel/vfs/node.h | 2 ++ src/user/app/test/main.c | 48 +++++++++++++++++++++++++----------------- src/user/app/yosh/main.c | 6 +++++- 14 files changed, 124 insertions(+), 27 deletions(-) diff --git a/doc/vfs.txt b/doc/vfs.txt index 680df73..7902148 100644 --- a/doc/vfs.txt +++ b/doc/vfs.txt @@ -20,6 +20,7 @@ The following syscall interface is given to the process (fd_t is a file descript - int read(fd_t file, size_t offset, size_t len, char *buffer) - int write(fd_t file, size_t offset, size_t len, char *buffer) - int link(char *from, char *to, int mode) +- int dev_control(fd_t file, char *data) struct file_info { int type @@ -58,5 +59,30 @@ File type flags : Device types : - DT_BLOCK -- DT_KEYBOARD -- DT_DISPLAY +- DT_PCKBD +- DT_VGATXT +- DT_VESAFB + + +Examples : + +- Standard file : + type : FT_FILE + size : file length +- Standard dir : + type : FT_DIR + size : number of entries +- A display adapter + type : FT_DEV + dev_type : DT_VGATXT + capabilities : read/write at given offset, mmap + size : width << 16 + height + content format : (raw) 16 bit for each character (attribute & text) +- A keyboard + type : FT_DEV + dev_type : DT_PCKBD + capabilities : read from a (FIFO) buffer, offset is ignored + size : unused (zero) + content format : read 16-bit keycodes from IBM-PC keyboard format + + diff --git a/src/include/tce/syscalls.h b/src/include/tce/syscalls.h index f32c225..983e89d 100644 --- a/src/include/tce/syscalls.h +++ b/src/include/tce/syscalls.h @@ -28,6 +28,7 @@ #define SC_READ 26 #define SC_WRITE 27 #define SC_LINK 28 +#define SC_DEVCONTROL 29 #define EX_PAGEFAULT 4000 #define EX_EXCEPTION 4001 diff --git a/src/include/tce/vfs.h b/src/include/tce/vfs.h index 36e391f..58e67f5 100644 --- a/src/include/tce/vfs.h +++ b/src/include/tce/vfs.h @@ -33,7 +33,10 @@ typedef struct _file_info { // device types #define DT_BLOCK 1 -#define DT_KEYBOARD 2 -#define DT_DISPLAY 3 +#define DT_PCKBD 2 +#define DT_VGATXT 3 +#define DT_VESAFB 4 + +#define DEV_CONTROL 0xB0057ED1 // hack, see doc/vfs.txt #endif diff --git a/src/kernel/dev/display.h b/src/kernel/dev/display.h index ec67e7e..963b5e6 100644 --- a/src/kernel/dev/display.h +++ b/src/kernel/dev/display.h @@ -22,7 +22,6 @@ class display : public node { vt *connected_vt; display(node* parent) : node(parent, FT_DEV) { - dev_type = DT_DISPLAY; connected_vt = 0; } virtual ~display() {} diff --git a/src/kernel/dev/keyboard.cpp b/src/kernel/dev/keyboard.cpp index 3f54b99..af4c380 100644 --- a/src/kernel/dev/keyboard.cpp +++ b/src/kernel/dev/keyboard.cpp @@ -77,7 +77,7 @@ static keymap default_km = { }; keyboard::keyboard(node *parent) : node(parent, FT_DEV) { - dev_type = DT_KEYBOARD; + dev_type = DT_PCKBD; km = &default_km; num = true; diff --git a/src/kernel/dev/ps2keyboard.cpp b/src/kernel/dev/ps2keyboard.cpp index 31cd75f..c7fc322 100644 --- a/src/kernel/dev/ps2keyboard.cpp +++ b/src/kernel/dev/ps2keyboard.cpp @@ -53,3 +53,4 @@ void ps2kbd::kbdIrq() { escaped = false; } } + diff --git a/src/kernel/dev/vgatxt.cpp b/src/kernel/dev/vgatxt.cpp index eb57eb9..7abbaf9 100644 --- a/src/kernel/dev/vgatxt.cpp +++ b/src/kernel/dev/vgatxt.cpp @@ -4,11 +4,12 @@ #include static uint16_t *video_memory = (uint16_t*)((size_t)K_HIGHHALF_ADDR + 0xB8000); +#define VIDMEM_SIZE (80 * 25 * 2) vgatxt *text_display; vgatxt::vgatxt(node *parent) : display(parent) { - // nothing to do, really + dev_type = DT_VGATXT; } int vgatxt::text_w() { @@ -52,3 +53,34 @@ void vgatxt::text_scroll(int n, uint8_t fgcolor, uint8_t bgcolor) { // TODO } } + + +// Operations as a FS node + +size_t vgatxt::get_size() { // size as a node of the filesystem + return (text_w() << 16) + text_h(); +} + +int vgatxt::read(size_t offset, size_t len, char *buffer) { + if (offset > VIDMEM_SIZE) return 0; + if (offset + len > VIDMEM_SIZE) len = VIDMEM_SIZE - offset; + + char *vm = (char*)video_memory; + memcpy(buffer, vm + offset, len); + return len; +} + +int vgatxt::write(size_t offset, size_t len, char *buffer) { + if (offset > VIDMEM_SIZE) return 0; + if (offset + len > VIDMEM_SIZE) len = VIDMEM_SIZE - offset; + + char *vm = (char*)video_memory; + memcpy(vm + offset, buffer, len); + return len; +} + +int vgatxt::dev_control(char *data) { + uint16_t *d = (uint16_t*)data; + text_setcsr(d[0], d[1], d[2] != 0); + return 0; +} diff --git a/src/kernel/dev/vgatxt.h b/src/kernel/dev/vgatxt.h index 550d4ba..bed743e 100644 --- a/src/kernel/dev/vgatxt.h +++ b/src/kernel/dev/vgatxt.h @@ -10,6 +10,13 @@ class vgatxt : public display { vgatxt(node *parent); virtual ~vgatxt() {} + // as a FS node + virtual size_t get_size(); + virtual int read(size_t offset, size_t len, char *buffer); + virtual int write(size_t offset, size_t len, char *buffer); + virtual int dev_control(char *data); + + // as a display virtual int text_w(); virtual int text_h(); virtual void text_setcsr(int l, int c, bool visible); diff --git a/src/kernel/mem/paging.cpp b/src/kernel/mem/paging.cpp index 436c888..4878ab3 100644 --- a/src/kernel/mem/paging.cpp +++ b/src/kernel/mem/paging.cpp @@ -146,6 +146,7 @@ uint32_t paging_fault(registers *regs) { if (regs->err_code & 0x4) dbg_printf(" user"); if (regs->err_code & 0x8) dbg_printf(" rsvd"); if (regs->err_code & 0x10) dbg_printf(" opfetch"); + dbg_printf("\n"); return 1; } return 0; diff --git a/src/kernel/task/syscall.cpp b/src/kernel/task/syscall.cpp index a3074b8..2e1350e 100644 --- a/src/kernel/task/syscall.cpp +++ b/src/kernel/task/syscall.cpp @@ -78,6 +78,10 @@ static void link_sc(registers *r) { r->eax = link((char*)r->ebx, (char*)r->ecx, r->edx); } +static void devcontrol_sc(registers *r) { + r->eax = dev_control(r->ebx, (char*)r->ecx); +} + int_callback syscalls[NUMBER_OF_SYSCALLS] = { // This must correspond to common/include/tce/syscalls.h 0, // 0 @@ -109,6 +113,7 @@ int_callback syscalls[NUMBER_OF_SYSCALLS] = { // This must correspond to common read_sc, write_sc, link_sc, + devcontrol_sc, 0 }; diff --git a/src/kernel/vfs/node.cpp b/src/kernel/vfs/node.cpp index 0b753af..d5d4c65 100644 --- a/src/kernel/vfs/node.cpp +++ b/src/kernel/vfs/node.cpp @@ -126,3 +126,9 @@ int link(char* from, char* to, int mode) { node *f2 = (to == 0 ? 0 : vfs_find(root, to)); return f1->link(f2, mode); } + +int dev_control(FILE file, char *data) { + node *f = vfs_read_fd(file); + if (f == 0) return E_INVALID_FD; + return f->dev_control(data); +} diff --git a/src/kernel/vfs/node.h b/src/kernel/vfs/node.h index 3b1c700..7fbc205 100644 --- a/src/kernel/vfs/node.h +++ b/src/kernel/vfs/node.h @@ -28,6 +28,7 @@ class node { virtual int add_child(char* name, node *child) { return E_NOT_IMPLEMENTED; } virtual size_t get_size() { return 0; } virtual int link(node* other, int mode) { return E_NOT_IMPLEMENTED; } + virtual int dev_control(char *data) { return E_NOT_IMPLEMENTED; } // kind of like dynamic_cast'ing these things virtual display *as_display() { return 0; } @@ -51,5 +52,6 @@ void close(FILE file); int read(FILE file, size_t offset, size_t len, char *buffer); int write(FILE file, size_t offset, size_t len, char *buffer); int link(char* from, char* to, int mode); +int dev_control(FILE file, char *data); #endif diff --git a/src/user/app/test/main.c b/src/user/app/test/main.c index 2c42cf8..d9b6332 100644 --- a/src/user/app/test/main.c +++ b/src/user/app/test/main.c @@ -1,14 +1,34 @@ #include #include #include +#include int threads = 1; +mutex_t d_mutex = MUTEX_UNLOCKED; +int d_pos = 0; +int vgatxt = -1; + +void display_it(char k) { + mutex_lock(&d_mutex); + + // just display some stuff on /.dev/vgatxt + if (vgatxt == -1) { + vgatxt = open("/.dev/vgatxt", FM_READ | FM_WRITE); + } + uint16_t c = k | (4 << 8); + write(vgatxt, 2 * d_pos, 2, (char*)&c); + + d_pos++; + + mutex_unlock(&d_mutex); +} + void thread_cascade(void* d) { int n = (int)d; char *v = malloc(2048); - if (!v) printk("!"); + if (!v) display_it('!'); if (d == 0) { //printk("{#} 0 cascade element started => end\n"); @@ -16,21 +36,21 @@ void thread_cascade(void* d) { } else { if (n < 0) { //printk("{#} - cascade element started\n"); - printk("-"); + display_it('-'); n = 0 - n; } else { //printk("{#} + cascade element started\n"); - printk("+"); + display_it('+'); } //printk("{#} FORK + ...\n"); - printk(">"); + display_it('>'); threads += 2; thread_new(thread_cascade, (void*)(n - 1)); //printk("{#} FORK - ...\n"); - printk("<"); + display_it('<'); thread_new(thread_cascade, (void*)(1 - n)); //printk("{#} Thread cascade element finished.\n"); - printk("."); + display_it('.'); } free(v); @@ -40,25 +60,15 @@ void thread_cascade(void* d) { void useless_thread(void* d) { while(1) { - printk("~"); + display_it('~'); schedule(); } } int main(int argc, char** args) { - char**a; - if (args != 0) { - printk("(test) args"); - for (a = args; *a != 0; a++) { - printk(" - "); - printk(*a); - } - printk("\n"); - } - - printk("(test) Creating thread cascade (total 2**6 = 64 threads)\n"); + printk("(test) Creating thread cascade (total 2**7 = 128 threads)\n"); thread_new(useless_thread, 0); - thread_new(thread_cascade, (void*)6); + thread_new(thread_cascade, (void*)7); while (1) { schedule(); diff --git a/src/user/app/yosh/main.c b/src/user/app/yosh/main.c index f7ee7e7..e989dc1 100644 --- a/src/user/app/yosh/main.c +++ b/src/user/app/yosh/main.c @@ -80,7 +80,11 @@ void ls_dir(int fd) { printf("\t"); if (info.type & FT_TERMINAL) { printf("%ix%i", info.size >> 16, info.size & 0xFFFF); - } else if ((info.type & FT_DEV) == 0) { + } else if (info.type & FT_DEV) { + if (info.dev_type == DT_VGATXT) { + printf("%ix%i", info.size >> 16, info.size & 0xFFFF); + } + } else { printf("%i", info.size); } -- cgit v1.2.3