aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-09 23:34:46 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-09 23:34:46 +0100
commit011d99fc5f90b1e2b51f7b96688bdcbbb944e104 (patch)
tree20a2a03ef168a09185b77fbea04adfeefc1d99bf
parente499d74b6f0b57f9a11486c346dbc335e4f8433d (diff)
downloadkogata-011d99fc5f90b1e2b51f7b96688bdcbbb944e104.tar.gz
kogata-011d99fc5f90b1e2b51f7b96688bdcbbb944e104.zip
VESA mode setting ; displays kogata logo!
-rw-r--r--menu_cdrom.lst2
-rw-r--r--src/common/include/framebuffer.h19
-rw-r--r--src/common/include/fs.h2
-rw-r--r--src/kernel/core/kmain.c5
-rw-r--r--src/kernel/dev/pciide.c6
-rw-r--r--src/kernel/dev/v86.c4
-rw-r--r--src/kernel/dev/vesa.c387
-rw-r--r--src/kernel/include/pager.h6
-rw-r--r--src/kernel/include/vfs.h4
-rw-r--r--src/kernel/user/pager.c71
10 files changed, 461 insertions, 45 deletions
diff --git a/menu_cdrom.lst b/menu_cdrom.lst
index a71f175..cba6724 100644
--- a/menu_cdrom.lst
+++ b/menu_cdrom.lst
@@ -2,7 +2,7 @@ timeout 10
default 0
title kogata OS
-kernel /kernel.bin root=io:/atapi0 root_opts=l init=root:/init.bin
+kernel /kernel.bin root=io:/disk/atapi0 root_opts=l init=root:/init.bin
title kogata OS without root
kernel /kernel.bin init=io:/mod/init.bin
diff --git a/src/common/include/framebuffer.h b/src/common/include/framebuffer.h
new file mode 100644
index 0000000..febbfaa
--- /dev/null
+++ b/src/common/include/framebuffer.h
@@ -0,0 +1,19 @@
+#pragma once
+
+typedef struct {
+ uint32_t width, height;
+ uint32_t pitch; // bytes per line
+ uint32_t bpp;
+} framebuffer_info_t;
+
+typedef struct {
+ int mode_number;
+ framebuffer_info_t geom;
+} fbdev_mode_info_t;
+
+#define IOCTL_FBDEV_GET_MODE_INFO 10
+#define IOCTL_FBDEV_SET_MODE 11
+
+#define IOCTL_FB_GET_INFO 12
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/common/include/fs.h b/src/common/include/fs.h
index 5a2fc84..e70ff55 100644
--- a/src/common/include/fs.h
+++ b/src/common/include/fs.h
@@ -11,7 +11,7 @@ typedef int fd_t;
#define FT_BLOCKDEV (0x04)
#define FT_CHARDEV (0x08)
#define FT_CHANNEL (0x10) // dual-pipe
-// #define FT_SOCKET (0x20) // Not yet! Semantics not defined. (TODO)
+#define FT_FRAMEBUFFER (0x20)
// FM_* enum describes modes for opening a file as well as authorized operations in stat_t
// (some flags are used only for open() or only in stat_t.access)
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index d23df1a..96c3cc1 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -222,7 +222,10 @@ fs_t *setup_iofs(multiboot_info_t *mbd) {
}
// Populate iofs with files for kernel modules
- ASSERT(fs_create(iofs, "/mod", FT_DIR));
+ const char *dirs[] = { "/mod", "/disk", "/input", "/display", 0 };
+ for (int i = 0; dirs[i] != 0; i++) {
+ ASSERT(fs_create(iofs, dirs[i], FT_DIR));
+ }
multiboot_module_t *mods = (multiboot_module_t*)mbd->mods_addr;
for (unsigned i = 0; i < mbd->mods_count; i++) {
char* modname = (char*)mods[i].string;
diff --git a/src/kernel/dev/pciide.c b/src/kernel/dev/pciide.c
index 600f08f..5abc148 100644
--- a/src/kernel/dev/pciide.c
+++ b/src/kernel/dev/pciide.c
@@ -692,10 +692,10 @@ void ide_register_device(ide_controller_t *c, uint8_t device, fs_t *iofs) {
char name[40];
if (d->type == IDE_ATAPI) {
- snprintf(name, 40, "/atapi%d", next_atapi_id);
+ snprintf(name, 40, "/disk/atapi%d", next_atapi_id);
next_atapi_id++;
} else {
- snprintf(name, 40, "/ata%d", next_ata_id);
+ snprintf(name, 40, "/disk/ata%d", next_ata_id);
next_ata_id++;
}
@@ -721,7 +721,7 @@ bool ide_vfs_open(fs_node_ptr n, int mode) {
bool ide_vfs_stat(fs_node_ptr n, stat_t *st) {
ide_vfs_dev_t *d = (ide_vfs_dev_t*)n;
- st->type = FT_BLOCKDEV;
+ st->type = FT_BLOCKDEV | FT_DEV;
st->access = (d->type == IDE_ATA ? FM_WRITE : 0) | FM_READ | FM_IOCTL;
st->size = d->c->devices[d->device].size * d->block_size;
diff --git a/src/kernel/dev/v86.c b/src/kernel/dev/v86.c
index 183b791..db84a4f 100644
--- a/src/kernel/dev/v86.c
+++ b/src/kernel/dev/v86.c
@@ -48,6 +48,9 @@ bool v86_begin_session() {
pd_map_page(addr, (uint32_t)addr / PAGE_SIZE, true);
}
pd_map_page(0, 0, true);
+ } else {
+ v86_prev_pagedir = get_current_pagedir();
+ switch_pagedir(v86_pagedir);
}
if (v86_thread == 0) {
@@ -70,6 +73,7 @@ bool v86_begin_session() {
void v86_end_session() {
switch_pagedir(v86_prev_pagedir);
+
v86_prev_pagedir = 0;
v86_caller_thread = 0;
diff --git a/src/kernel/dev/vesa.c b/src/kernel/dev/vesa.c
index 6b23a34..9113404 100644
--- a/src/kernel/dev/vesa.c
+++ b/src/kernel/dev/vesa.c
@@ -1,8 +1,164 @@
#include <string.h>
+#include <framebuffer.h> // common header
+
+#include <vfs.h>
+#include <nullfs.h>
+
#include <dev/vesa.h>
#include <dev/v86.h>
+// ---- kogata logo data (thank you gimp!)
+
+
+/* GIMP RGB C-Source image dump 1-byte-run-length-encoded (kogata-logo-small.c) */
+
+#define KOGATA_LOGO_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \
+{ unsigned int __bpp; unsigned char *__ip; const unsigned char *__il, *__rd; \
+ __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \
+ __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \
+ while (__ip < __il) { unsigned int __l = *(__rd++); \
+ if (__l & 128) { __l = __l - 128; \
+ do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \
+ } else { __l *= 4; memcpy (__ip, __rd, __l); \
+ __ip += __l; __rd += __l; } } \
+ } else { /* RGB */ \
+ while (__ip < __il) { unsigned int __l = *(__rd++); \
+ if (__l & 128) { __l = __l - 128; \
+ do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \
+ } else { __l *= 3; memcpy (__ip, __rd, __l); \
+ __ip += __l; __rd += __l; } } \
+ } } while (0)
+static const struct {
+ unsigned int width;
+ unsigned int height;
+ unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
+ unsigned char rle_pixel_data[2940 + 1];
+} kogata_logo = {
+ 128, 128, 3,
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
+ "\377\377\377\377\377\377\377\377\377\377\304\377\377\377\5\302\302\302\264"
+ "\264\264\274\274\274\314\314\314\355\355\355\371\377\377\377\2\352\352\352"
+ "\1\1\1\206\0\0\0\2+++\217\217\217\366\377\377\377\1\203\203\203\212\0\0\0"
+ "\1yyy\364\377\377\377\1\236\236\236\213\0\0\0\1$$$\364\377\377\377\1\7\7"
+ "\7\213\0\0\0\3\16\16\16\344\344\344\376\376\376\361\377\377\377\1\331\331"
+ "\331\215\0\0\0\1\221\221\221\362\377\377\377\2\373\373\373---\214\0\0\0\1"
+ "\210\210\210\363\377\377\377\1www\214\0\0\0\1\202\202\202\363\377\377\377"
+ "\1|||\214\0\0\0\1\177\177\177\363\377\377\377\1GGG\214\0\0\0\1\274\274\274"
+ "\362\377\377\377\1\354\354\354\214\0\0\0\2\7\7\7\300\300\300\362\377\377"
+ "\377\1\23\23\23\215\0\0\0\1\330\330\330\361\377\377\377\1WWW\215\0\0\0\1"
+ "\26\26\26\361\377\377\377\1\204\204\204\216\0\0\0\1\347\347\347\360\377\377"
+ "\377\1\245\245\245\216\0\0\0\1\355\355\355\360\377\377\377\1\274\274\274"
+ "\215\0\0\0\1\2\2\2\361\377\377\377\1\317\317\317\215\0\0\0\1""111\361\377"
+ "\377\377\1\342\342\342\215\0\0\0\1JJJ\361\377\377\377\1\365\365\365\215\0"
+ "\0\0\1]]]\362\377\377\377\215\0\0\0\1jjj\362\377\377\377\215\0\0\0\1uuu\362"
+ "\377\377\377\215\0\0\0\1\177\177\177\362\377\377\377\215\0\0\0\1\212\212"
+ "\212\362\377\377\377\1\4\4\4\214\0\0\0\1\225\225\225\362\377\377\377\1\13"
+ "\13\13\214\0\0\0\1\240\240\240\362\377\377\377\1\21\21\21\214\0\0\0\1\252"
+ "\252\252\362\377\377\377\1\26\26\26\214\0\0\0\1\260\260\260\362\377\377\377"
+ "\1\33\33\33\214\0\0\0\1\265\265\265\362\377\377\377\1!!!\214\0\0\0\1\273"
+ "\273\273\362\377\377\377\1&&&\214\0\0\0\1\300\300\300\362\377\377\377\1,"
+ ",,\214\0\0\0\1\306\306\306\362\377\377\377\1///\214\0\0\0\1\314\314\314\362"
+ "\377\377\377\1""222\214\0\0\0\1\321\321\321\362\377\377\377\1""555\214\0"
+ "\0\0\1\327\327\327\362\377\377\377\1""777\214\0\0\0\1\334\334\334\362\377"
+ "\377\377\1;;;\214\0\0\0\1\336\336\336\217\377\377\377\202\376\376\376\7p"
+ "pp###\14\14\14\30\30\30@@@|||\307\307\307\332\377\377\377\1===\214\0\0\0"
+ "\1\340\340\340\217\377\377\377\1\352\352\352\211\0\0\0\2GGG\301\301\301\327"
+ "\377\377\377\1@@@\214\0\0\0\1\343\343\343\217\377\377\377\1qqq\213\0\0\0"
+ "\3\6\6\6ttt\352\352\352\324\377\377\377\1CCC\214\0\0\0\1\344\344\344\217"
+ "\377\377\377\1\254\254\254\216\0\0\0\2***\277\277\277\255\377\377\377\3\266"
+ "\266\266fffvvv\242\377\377\377\1FFF\214\0\0\0\1\346\346\346\220\377\377\377"
+ "\1###\217\0\0\0\2\34\34\34\313\313\313\250\377\377\377\3\375\375\375\363"
+ "\363\363\37\37\37\203\0\0\0\1uuu\241\377\377\377\1FFF\214\0\0\0\1\350\350"
+ "\350\221\377\377\377\1\11\11\11\220\0\0\0\1""888\247\377\377\377\2\363\363"
+ "\363SSS\204\0\0\0\1\30\30\30\241\377\377\377\1EEE\214\0\0\0\1\352\352\352"
+ "\220\377\377\377\3\376\376\376\377\377\377\27\27\27\220\0\0\0\2\7\7\7\316"
+ "\316\316\245\377\377\377\1\26\26\26\206\0\0\0\215\377\377\377\1\335\335\335"
+ "\202\273\273\273\1\372\372\372\220\377\377\377\1DDD\214\0\0\0\1\355\355\355"
+ "\223\377\377\377\1\26\26\26\221\0\0\0\1ppp\243\377\377\377\1DDD\207\0\0\0"
+ "\211\377\377\377\3\367\367\367\223\223\223333\204\0\0\0\1___\220\377\377"
+ "\377\1DDD\214\0\0\0\1\356\356\356\223\377\377\377\2\373\373\373\17\17\17"
+ "\221\0\0\0\1kkk\241\377\377\377\1\311\311\311\210\0\0\0\1\354\354\354\206"
+ "\377\377\377\2\273\273\273...\206\0\0\0\1\36\36\36\221\377\377\377\1CCC\214"
+ "\0\0\0\1\361\361\361\224\377\377\377\1\345\345\345\222\0\0\0\1uuu\240\377"
+ "\377\377\1\22\22\22\210\0\0\0\1\244\244\244\203\377\377\377\3\376\376\376"
+ "\226\226\226\20\20\20\207\0\0\0\1BBB\222\377\377\377\1BBB\214\0\0\0\1\361"
+ "\361\361\224\377\377\377\2\376\376\376\214\214\214\222\0\0\0\1\330\330\330"
+ "\236\377\377\377\1[[[\211\0\0\0\4\22\22\22\277\277\277\217\217\217---\211"
+ "\0\0\0\1~~~\223\377\377\377\1AAA\214\0\0\0\1\362\362\362\226\377\377\377"
+ "\1ttt\221\0\0\0\1\14\14\14\235\377\377\377\1\374\374\374\225\0\0\0\2\26\26"
+ "\26\362\362\362\224\377\377\377\1@@@\214\0\0\0\1\363\363\363\227\377\377"
+ "\377\1FFF\221\0\0\0\1BBB\234\377\377\377\1DDD\224\0\0\0\1\40\40\40\226\377"
+ "\377\377\1;;;\214\0\0\0\1\363\363\363\230\377\377\377\1\36\36\36\221\0\0"
+ "\0\1\315\315\315\232\377\377\377\1\355\355\355\224\0\0\0\1+++\227\377\377"
+ "\377\1""555\214\0\0\0\1\364\364\364\230\377\377\377\1\373\373\373\221\0\0"
+ "\0\1\34\34\34\232\377\377\377\1???\223\0\0\0\1---\230\377\377\377\1""000"
+ "\214\0\0\0\1\365\365\365\231\377\377\377\1\206\206\206\221\0\0\0\1\261\261"
+ "\261\230\377\377\377\1\364\364\364\223\0\0\0\1FFF\231\377\377\377\1***\214"
+ "\0\0\0\1\365\365\365\232\377\377\377\1]]]\220\0\0\0\1\23\23\23\230\377\377"
+ "\377\1TTT\222\0\0\0\1)))\232\377\377\377\1%%%\214\0\0\0\1\365\365\365\233"
+ "\377\377\377\1'''\220\0\0\0\1\264\264\264\227\377\377\377\222\0\0\0\1\36"
+ "\36\36\233\377\377\377\1\37\37\37\214\0\0\0\1\366\366\366\234\377\377\377"
+ "\1\14\14\14\217\0\0\0\1&&&\226\377\377\377\1\231\231\231\221\0\0\0\1\24\24"
+ "\24\234\377\377\377\1\27\27\27\214\0\0\0\1\366\366\366\234\377\377\377\1"
+ "\326\326\326\220\0\0\0\1\346\346\346\225\377\377\377\1\24\24\24\221\0\0\0"
+ "\1\370\370\370\234\377\377\377\1\11\11\11\214\0\0\0\1\367\367\367\235\377"
+ "\377\377\1kkk\217\0\0\0\1\207\207\207\224\377\377\377\1\346\346\346\221\0"
+ "\0\0\2\215\215\215\376\376\376\234\377\377\377\215\0\0\0\1\370\370\370\236"
+ "\377\377\377\1""222\216\0\0\0\1>>>\224\377\377\377\1\207\207\207\220\0\0"
+ "\0\1www\236\377\377\377\215\0\0\0\1\370\370\370\237\377\377\377\1\24\24\24"
+ "\215\0\0\0\1\24\24\24\224\377\377\377\1:::\217\0\0\0\1NNN\237\377\377\377"
+ "\215\0\0\0\1\370\370\370\237\377\377\377\1\355\355\355\215\0\0\0\1\23\23"
+ "\23\224\377\377\377\1\16\16\16\216\0\0\0\1!!!\237\377\377\377\1\372\372\372"
+ "\215\0\0\0\1\371\371\371\240\377\377\377\1\200\200\200\214\0\0\0\1CCC\224"
+ "\377\377\377\1\25\25\25\216\0\0\0\1\361\361\361\237\377\377\377\1\346\346"
+ "\346\215\0\0\0\1\372\372\372\241\377\377\377\1]]]\213\0\0\0\1\244\244\244"
+ "\224\377\377\377\1""999\215\0\0\0\1BBB\240\377\377\377\1\320\320\320\215"
+ "\0\0\0\1\372\372\372\242\377\377\377\1""111\211\0\0\0\1\22\22\22\225\377"
+ "\377\377\1ppp\215\0\0\0\1\254\254\254\240\377\377\377\1\272\272\272\215\0"
+ "\0\0\1\373\373\373\243\377\377\377\1&&&\210\0\0\0\1\325\325\325\225\377\377"
+ "\377\1\275\275\275\215\0\0\0\1\261\261\261\240\377\377\377\1\244\244\244"
+ "\215\0\0\0\1\373\373\373\244\377\377\377\1###\206\0\0\0\1kkk\227\377\377"
+ "\377\215\0\0\0\1\217\217\217\240\377\377\377\1\211\211\211\215\0\0\0\1\374"
+ "\374\374\245\377\377\377\1CCC\204\0\0\0\1^^^\230\377\377\377\1HHH\214\0\0"
+ "\0\1sss\240\377\377\377\1ccc\215\0\0\0\1\374\374\374\246\377\377\377\4\335"
+ "\335\335sssooo\330\330\330\231\377\377\377\1\324\324\324\214\0\0\0\1fff\216"
+ "\377\377\377\3\335\335\335\312\312\312\356\356\356\217\377\377\377\1===\215"
+ "\0\0\0\1\375\375\375\304\377\377\377\1\35\35\35\213\0\0\0\1\233\233\233\216"
+ "\377\377\377\1""333\202\0\0\0\4\3\3\3QQQ\235\235\235\371\371\371\213\377"
+ "\377\377\1\14\14\14\215\0\0\0\1\375\375\375\304\377\377\377\1\302\302\302"
+ "\212\0\0\0\1\14\14\14\217\377\377\377\2\371\371\371\30\30\30\205\0\0\0\3"
+ "$$$\223\223\223\361\361\361\207\377\377\377\1\367\367\367\216\0\0\0\1\376"
+ "\376\376\305\377\377\377\1""000\211\0\0\0\1\334\334\334\221\377\377\377\1"
+ "///\207\0\0\0\3\35\35\35\200\200\200\321\321\321\204\377\377\377\1\241\241"
+ "\241\216\0\0\0\1\376\376\376\305\377\377\377\1\373\373\373\210\0\0\0\1\211"
+ "\211\211\223\377\377\377\1bbb\212\0\0\0\4///sss\222\222\222\3\3\3\216\0\0"
+ "\0\1\376\376\376\306\377\377\377\2\331\331\331\12\12\12\204\0\0\0\2""111"
+ "\364\364\364\225\377\377\377\1\204\204\204\232\0\0\0\1\2\2\2\311\377\377"
+ "\377\4\267\267\267\221\221\221\244\244\244\356\356\356\230\377\377\377\1"
+ "\215\215\215\231\0\0\0\1ccc\346\377\377\377\1\223\223\223\230\0\0\0\1\312"
+ "\312\312\346\377\377\377\2\376\376\376\221\221\221\226\0\0\0\1\11\11\11\351"
+ "\377\377\377\1\210\210\210\225\0\0\0\1qqq\352\377\377\377\1rrr\224\0\0\0"
+ "\1\334\334\334\353\377\377\377\1>>>\222\0\0\0\1\21\21\21\355\377\377\377"
+ "\1\26\26\26\221\0\0\0\1~~~\355\377\377\377\1\325\325\325\221\0\0\0\1\355"
+ "\355\355\356\377\377\377\1JJJ\217\0\0\0\1!!!\360\377\377\377\1\7\7\7\216"
+ "\0\0\0\1\232\232\232\360\377\377\377\1\236\236\236\216\0\0\0\1\376\376\376"
+ "\361\377\377\377\1\16\16\16\214\0\0\0\1""222\362\377\377\377\1\232\232\232"
+ "\214\0\0\0\1\256\256\256\363\377\377\377\213\0\0\0\1\1\1\1\364\377\377\377"
+ "\1SSS\212\0\0\0\1kkk\364\377\377\377\1\316\316\316\212\0\0\0\1\342\342\342"
+ "\365\377\377\377\1\5\5\5\210\0\0\0\1(((\366\377\377\377\1bbb\210\0\0\0\1"
+ "\277\277\277\366\377\377\377\1\270\270\270\207\0\0\0\1!!!\370\377\377\377"
+ "\207\0\0\0\1\354\354\354\370\377\377\377\1CCC\205\0\0\0\1vvv\371\377\377"
+ "\377\1\320\320\320\204\0\0\0\1VVV\373\377\377\377\1""666\202\0\0\0\1jjj\375"
+ "\377\377\377\2\276\276\276\360\360\360\377\377\377\377\377\377\377\377\377"
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
+ "\377\324\377\377\377",
+};
+
// ---- VESA data structures
typedef struct {
@@ -39,8 +195,50 @@ typedef struct {
uint16_t reserved2;
} __attribute__((packed)) vbe_mode_info_block_t;
+// ---- VESA driver data structures
+
+typedef struct {
+ framebuffer_info_t info;
+ uint16_t vesa_mode_id;
+ void* phys_fb_addr;
+} vesa_mode_t;
+
+typedef struct {
+ vesa_mode_t *modes;
+
+ int nmodes;
+ int current_mode;
+
+ pager_t *pager;
+} vesa_driver_t;
+
// ---- VESA code
+bool vesa_open(fs_node_ptr n, int mode);
+size_t vesa_read(fs_handle_t *f, size_t offset, size_t len, char* buf);
+size_t vesa_write(fs_handle_t *f, size_t offset, size_t len, const char* buf);
+void vesa_close(fs_handle_t *f);
+int vesa_ioctl(fs_node_ptr n, int command, void* data);
+bool vesa_stat(fs_node_ptr n, stat_t *st);
+
+bool vesa_set_mode(vesa_driver_t *d, int n);
+
+fs_node_ops_t vesa_fs_ops = {
+ .open = vesa_open,
+ .read = vesa_read,
+ .write = vesa_write,
+ .close = vesa_close,
+ .ioctl = vesa_ioctl,
+ .stat = vesa_stat,
+ .readdir = 0,
+ .poll = 0,
+ .walk = 0,
+ .delete = 0,
+ .move = 0,
+ .create = 0,
+ .dispose = 0,
+};
+
void vesa_detect(fs_t *iofs) {
if (!v86_begin_session()) return;
@@ -52,33 +250,178 @@ void vesa_detect(fs_t *iofs) {
v86_regs.es = V86_SEG_OF_LIN(i);
v86_regs.di = V86_OFF_OF_LIN(i);
- if (v86_bios_int(0x10)) {
- if (v86_regs.ax == 0x004F) {
- dbg_printf("Detected VESA (sig %s, ver 0x%x, oem %s) with %d kb ram.\n",
- i->vbe_signature, i->vbe_version, v86_lin_of_fp(i->oem_string_ptr), 64 * i->total_memory);
-
- vbe_mode_info_block_t *mi = (vbe_mode_info_block_t*)v86_alloc(256);
-
- uint16_t *modes = (uint16_t*)v86_lin_of_fp(i->video_mode_ptr);
- for (int n = 0; modes[n] != 0xFFFF; n++) {
- v86_regs.ax = 0x4F01;
- v86_regs.cx = modes[n];
- v86_regs.es = V86_SEG_OF_LIN(mi);
- v86_regs.di = V86_OFF_OF_LIN(mi);
- if (v86_bios_int(0x10) && v86_regs.ax == 0x004F) {
- dbg_printf("Mode 0x%x : %dx%dx%d at 0x%p\n", modes[n], mi->Xres, mi->Yres, mi->bpp, mi->physbase);
- } else {
- dbg_printf("Mode 0x%x : could not get info\n", modes[n]);
+ vesa_mode_t *mode_data = 0;
+ int mode_data_c = 0;
+
+ if (!v86_bios_int(0x10) || v86_regs.ax != 0x004F) {
+ dbg_printf("Could not call int 0x10 to detect VESA.\n");
+ goto end_detect;
+ }
+
+ dbg_printf("Detected VESA (sig %s, ver 0x%x, oem %s) with %d kb ram.\n",
+ i->vbe_signature, i->vbe_version, v86_lin_of_fp(i->oem_string_ptr), 64 * i->total_memory);
+
+ vbe_mode_info_block_t *mi = (vbe_mode_info_block_t*)v86_alloc(256);
+
+ uint16_t *modes = (uint16_t*)v86_lin_of_fp(i->video_mode_ptr);
+ uint16_t *last_mode = modes;
+ while (*last_mode != 0xFFFF) last_mode++;
+
+ mode_data = (vesa_mode_t*)malloc((last_mode - modes) * sizeof(vesa_mode_t));
+ if (mode_data == 0) goto end_detect;
+
+ for (uint16_t *mode = modes; mode < last_mode; mode++) {
+ v86_regs.ax = 0x4F01;
+ v86_regs.cx = *mode;
+ v86_regs.es = V86_SEG_OF_LIN(mi);
+ v86_regs.di = V86_OFF_OF_LIN(mi);
+ if (!v86_bios_int(0x10) || v86_regs.ax != 0x004F) continue;
+
+ if ((mi->attributes & 0x90) != 0x90) continue; // not linear framebuffer
+ if (mi->memory_model != 4 && mi->memory_model != 6) continue;
+
+ int x = mode_data_c;
+ mode_data[x].info.width = mi->Xres;
+ mode_data[x].info.height = mi->Yres;
+ mode_data[x].info.bpp = mi->bpp;
+ mode_data[x].info.pitch = mi->pitch;
+ mode_data[x].phys_fb_addr = (void*)mi->physbase;
+ mode_data[x].vesa_mode_id = *mode;
+ mode_data_c++;
+ }
+
+end_detect:
+ v86_end_session();
+
+ if (mode_data == 0) return;
+
+ vesa_driver_t *d = (vesa_driver_t*)malloc(sizeof(vesa_driver_t));
+ if (d == 0) goto fail_setup;
+
+ d->pager = new_device_pager(0, 0);
+ if (d == 0) goto fail_setup;
+
+ d->modes = mode_data;
+ d->nmodes = mode_data_c;
+ d->current_mode = -1;
+
+ bool add_ok = nullfs_add_node(iofs, "/display/vesa", d, &vesa_fs_ops, d->pager);
+ if (!add_ok) goto fail_setup;
+
+ // Lookup a valid mode and set it
+ for (int i = 0; i < mode_data_c; i++) {
+ if (mode_data[i].info.bpp == 24 && mode_data[i].info.width <= 800 && mode_data[i].info.width >= 600) {
+ if (vesa_set_mode(d, i)) break;
+ }
+ }
+
+ dbg_printf("Successfully registered VESA driver (%d modes)\n", mode_data_c);
+ return; // success
+
+fail_setup:
+ if (d != 0 && d->pager != 0) delete_pager(d->pager);
+ if (d) free(d);
+ if (mode_data) free(mode_data);
+}
+
+bool vesa_open(fs_node_ptr n, int mode) {
+ int ok_modes = FM_READ | FM_WRITE | FM_MMAP;
+ if (mode & ~ok_modes) return false;
+
+ return true;
+}
+
+size_t vesa_read(fs_handle_t *f, size_t offset, size_t len, char* buf) {
+ vesa_driver_t *d = (vesa_driver_t*)f->node->data;
+
+ return pager_read(d->pager, offset, len, buf);
+}
+
+size_t vesa_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
+ vesa_driver_t *d = (vesa_driver_t*)f->node->data;
+
+ return pager_write(d->pager, offset, len, buf);
+}
+
+void vesa_close(fs_handle_t *f) {
+ // nothing to do
+}
+
+int vesa_ioctl(fs_node_ptr n, int command, void* data) {
+ // TODO
+ return 0;
+}
+
+bool vesa_stat(fs_node_ptr n, stat_t *st) {
+ vesa_driver_t *d = (vesa_driver_t*)d;
+
+ framebuffer_info_t *i = (d->current_mode == -1 ? 0 : &d->modes[d->current_mode].info);
+
+ st->type = FT_DEV | FT_FRAMEBUFFER;
+ st->size = (i ? i->width * i->pitch : 0);
+ st->access = FM_READ | FM_WRITE | FM_MMAP;
+
+ return true;
+}
+
+bool vesa_set_mode(vesa_driver_t *d, int n) {
+ ASSERT(n >= 0 && n < d->nmodes);
+
+ if (!v86_begin_session()) return false;
+
+ bool ok = true;
+
+ v86_regs.ax = 0x4F02;
+ v86_regs.bx = d->modes[n].vesa_mode_id;
+ if (!v86_bios_int(0x10) || v86_regs.ax != 0x004F) ok = false;
+
+ v86_end_session();
+
+ if (ok) {
+ size_t fb_size = d->modes[n].info.pitch * d->modes[n].info.width;
+
+ d->current_mode = n;
+ change_device_pager(d->pager, fb_size, d->modes[n].phys_fb_addr);
+
+ // clear screen & put kogata logo
+ void* region = region_alloc(fb_size, "VESA");
+ if (region) {
+ bool ok = true;
+ for (void* x = region; x < region + fb_size; x += PAGE_SIZE) {
+ void* paddr = d->modes[n].phys_fb_addr + (x - region);
+ if (!pd_map_page(x, (uint32_t)paddr / PAGE_SIZE, true)) ok = false;
+ }
+ if (ok) {
+ memset(region, 255, fb_size);
+
+ void* buffer = malloc(kogata_logo.width * kogata_logo.height * kogata_logo.bytes_per_pixel);
+ if (buffer) {
+ KOGATA_LOGO_RUN_LENGTH_DECODE(buffer,
+ kogata_logo.rle_pixel_data,
+ kogata_logo.width * kogata_logo.height,
+ kogata_logo.bytes_per_pixel);
+
+ int tly = (d->modes[n].info.height / 2) - (kogata_logo.height / 2);
+ int tlx = (d->modes[n].info.width / 2) - (kogata_logo.width / 2);
+ int mbpp = (d->modes[n].info.bpp / 8);
+
+ for (unsigned l = 0; l < kogata_logo.height; l++) {
+ memcpy(region + (tly + l) * d->modes[n].info.pitch + tlx * mbpp,
+ buffer + kogata_logo.width * l * kogata_logo.bytes_per_pixel,
+ kogata_logo.width * kogata_logo.bytes_per_pixel);
+ }
+
+ free(buffer);
}
}
- } else {
- dbg_printf("Error in BIOS int 0x10/0x4F00.\n");
+ for (void* x = region; x < region + fb_size; x += PAGE_SIZE) {
+ pd_unmap_page(x);
+ }
+ region_free(region);
}
- } else {
- dbg_printf("Could not call BIOS int 0x10.\n");
}
- v86_end_session();
+ return ok;
}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/include/pager.h b/src/kernel/include/pager.h
index 7f93b8c..03e5da4 100644
--- a/src/kernel/include/pager.h
+++ b/src/kernel/include/pager.h
@@ -37,7 +37,7 @@ typedef struct pager {
vfs_pager_ops_t *ops;
} vfs_pager;
struct {
- size_t phys_offset;
+ void* phys_offset;
} device_pager;
};
@@ -51,7 +51,9 @@ typedef struct pager {
pager_t* new_swap_pager(size_t size);
pager_t* new_vfs_pager(size_t size, fs_node_t* vfs_node, vfs_pager_ops_t *vfs_ops);
-pager_t* new_device_pager(size_t size, size_t phys_offset);
+pager_t* new_device_pager(size_t size, void* phys_offset);
+
+void change_device_pager(pager_t *p, size_t new_size, void* new_phys_offset);
void delete_pager(pager_t *p);
diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h
index 2d50c9a..3d225c5 100644
--- a/src/kernel/include/vfs.h
+++ b/src/kernel/include/vfs.h
@@ -88,11 +88,11 @@ typedef struct fs_node_ops {
void (*close)(fs_handle_t *f);
bool (*stat)(fs_node_ptr n, stat_t *st);
- int (*ioctl)(fs_node_ptr f, int command, void* data);
+ int (*ioctl)(fs_node_ptr n, int command, void* data);
bool (*walk)(fs_node_t *n, const char* file, struct fs_node *node_d);
bool (*delete)(fs_node_ptr n, const char* file);
- bool (*move)(fs_node_ptr dir, const char* old_name, struct fs_node *new_parent, const char *new_name);
+ bool (*move)(fs_node_ptr n, const char* old_name, struct fs_node *new_parent, const char *new_name);
bool (*create)(fs_node_ptr n, const char* name, int type); // create sub-node in directory
void (*dispose)(fs_node_t *n);
} fs_node_ops_t;
diff --git a/src/kernel/user/pager.c b/src/kernel/user/pager.c
index 20c7014..79f293b 100644
--- a/src/kernel/user/pager.c
+++ b/src/kernel/user/pager.c
@@ -7,8 +7,7 @@
#define ENT_FRAME_SHIFT 12
-// TODO TODO TODO TODO !!! when resizing/paging out, make sure to UNMAP ALL PAGES from processes!!
-
+void pager_unmap(pager_t *p, size_t offset, size_t len);
// ========== //
// SWAP PAGER //
@@ -89,9 +88,6 @@ void swap_page_release(pager_t *p, size_t offset, size_t len) {
bool swap_pager_resize(pager_t *p, size_t new_size) {
// later : remove unused pages in swap file
- swap_page_release(p, PAGE_ALIGN_UP(new_size), p->size - PAGE_ALIGN_UP(new_size));
-
- p->size = new_size;
return true;
}
@@ -241,9 +237,6 @@ bool vfs_pager_resize(pager_t *p, size_t new_size) {
if (p->vfs_pager.ops->resize == 0) return false;
if (!p->vfs_pager.ops->resize(p->vfs_pager.node, new_size)) return false;
- vfs_page_release(p, PAGE_ALIGN_UP(new_size), p->size - PAGE_ALIGN_UP(new_size));
-
- p->size = new_size;
return true;
}
@@ -252,16 +245,17 @@ bool vfs_pager_resize(pager_t *p, size_t new_size) {
// ============ //
void device_page_in(pager_t *p, size_t offset, size_t len);
+void device_page_release(pager_t *p, size_t offset, size_t len);
pager_ops_t device_pager_ops = {
.page_in = device_page_in,
.page_commit = 0,
.page_out = 0,
- .page_release = 0,
+ .page_release = device_page_release,
.resize = 0,
};
-pager_t *new_device_page(size_t size, size_t phys_offset) {
+pager_t *new_device_pager(size_t size, void* phys_offset) {
ASSERT(PAGE_ALIGNED(phys_offset));
pager_t *p = (pager_t*)malloc(sizeof(pager_t));
@@ -288,15 +282,57 @@ void device_page_in(pager_t *p, size_t offset, size_t len) {
for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
if (hashtbl_find(p->pages, (void*)page) == 0) {
- hashtbl_add(p->pages, (void*)page, (void*)(p->device_pager.phys_offset + page));
+ hashtbl_add(p->pages, (void*)page, p->device_pager.phys_offset + page);
}
}
}
+void device_page_release(pager_t *p, size_t offset, size_t len) {
+ ASSERT(PAGE_ALIGNED(offset));
+
+ for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
+ hashtbl_remove(p->pages, (void*)page);
+ }
+}
+
+void change_device_pager(pager_t *p, size_t new_size, void* new_phys_offset) {
+ if (p->ops != &device_pager_ops) return;
+
+ mutex_lock(&p->lock);
+
+ pager_unmap(p, 0, p->size);
+ device_page_release(p, 0, p->size);
+
+ p->size = new_size;
+ p->device_pager.phys_offset = new_phys_offset;
+
+ mutex_unlock(&p->lock);
+}
+
// ======================= //
// GENERIC PAGER FUNCTIONS //
// ======================= //
+// ---- Pager internals
+
+void pager_unmap(pager_t *p, size_t offset, size_t len) {
+ pagedir_t *r = get_current_pagedir();
+
+ for (user_region_t *it = p->maps; it != 0; it = it->next_for_pager) {
+ switch_pagedir(it->proc->pd);
+
+ for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
+ void* addr = it->addr + offset - it->offset;
+
+ if (pd_get_entry(addr) & PTE_PRESENT) pd_unmap_page(addr);
+ }
+ }
+
+ switch_pagedir(r);
+}
+
+// ---- Pager public interface
+
void delete_pager(pager_t *p) {
ASSERT(p->maps == 0);
@@ -309,12 +345,21 @@ void delete_pager(pager_t *p) {
free(p);
}
-bool pager_resize(pager_t *p, size_t newsize) {
+bool pager_resize(pager_t *p, size_t new_size) {
if (!p->ops->resize) return false;
mutex_lock(&p->lock);
- bool ret = p->ops->resize(p, newsize);
+ bool ret = p->ops->resize(p, new_size);
+
+ if (ret) {
+ if (PAGE_ALIGN_UP(new_size) < p->size) {
+ pager_unmap(p, PAGE_ALIGN_UP(new_size), p->size - PAGE_ALIGN_UP(new_size));
+ if (p->ops->page_release)
+ p->ops->page_release(p, PAGE_ALIGN_UP(new_size), p->size - PAGE_ALIGN_UP(new_size));
+ }
+ p->size = new_size;
+ }
mutex_unlock(&p->lock);