summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2021-03-03 22:43:17 -0500
committerBenji Dial <benji6283@gmail.com>2021-03-03 22:43:17 -0500
commit81df4702c424f91cca5570ab2554d1d4cbae534d (patch)
treeaa8704b2fdf7a4bd79d85f480dc9fd8f8db02547 /src/kernel
parent43693f88c79467b741b3f899799082e791656d1b (diff)
downloadportland-os-81df4702c424f91cca5570ab2554d1d4cbae534d.tar.gz
64kiB kernel area, ps/2 mouse support, signed decimals in knob format
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/idt.c6
-rw-r--r--src/kernel/isrs.asm17
-rw-r--r--src/kernel/kbd.c84
-rw-r--r--src/kernel/paging.c4
-rw-r--r--src/kernel/task.c6
-rw-r--r--src/kernel/window.c131
-rw-r--r--src/kernel/window.h3
7 files changed, 205 insertions, 46 deletions
diff --git a/src/kernel/idt.c b/src/kernel/idt.c
index 1a78da0..f07ef1d 100644
--- a/src/kernel/idt.c
+++ b/src/kernel/idt.c
@@ -219,6 +219,7 @@ extern isr_t quit_isr;
extern isr_t yield_isr;
extern isr_t kbd_isr;
+extern isr_t mouse_isr;
extern isr_t udf_isr;
extern isr_t dfa_isr;
@@ -325,6 +326,7 @@ void init_idt() {
register_int(0x39, &yield_isr, 3);
register_int(0x21, &kbd_isr, 0);
+ register_int(0x2c, &mouse_isr, 0);
register_int(0x08, &udf_isr, 0);
register_int(0x08, &dfa_isr, 0);
@@ -346,8 +348,8 @@ void init_idt() {
outb(PIC_MDATA, 0x01);
outb(PIC_SDATA, 0x01);
- outb(PIC_MDATA, 0xfd);
- outb(PIC_SDATA, 0xff);
+ outb(PIC_MDATA, 0xf9);
+ outb(PIC_SDATA, 0xef);
asm volatile (
"lidt %0"
diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm
index 1aba884..70bab19 100644
--- a/src/kernel/isrs.asm
+++ b/src/kernel/isrs.asm
@@ -5,6 +5,7 @@ global quit_isr
global yield_isr
global _start_user_mode
global kbd_isr
+global mouse_isr
global udf_isr
global dfa_isr
@@ -133,6 +134,22 @@ _start_user_mode:
sub esp, 4
jmp yield_isr.return_to_task
+mouse_isr:
+ push eax
+ push ecx
+ push edx
+
+ call on_kbd_isr
+
+ mov al, 0x20
+ out 0x00a0, al
+ out 0x0020, al
+
+ pop edx
+ pop ecx
+ pop eax
+ iret
+
kbd_isr:
push eax
push ecx
diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c
index 47894cd..004706f 100644
--- a/src/kernel/kbd.c
+++ b/src/kernel/kbd.c
@@ -21,16 +21,36 @@ enum {
enum {
PS2C_READ_CONFIG = 0x20,
PS2C_WRITE_CONFIG = 0x60,
+ PS2C_AUX_ENABLE = 0xa8,
PS2C_DISABLE = 0xad,
- PS2C_ENABLE = 0xae
+ PS2C_ENABLE = 0xae,
+ PS2C_SEND_AUX = 0xd4
};
enum {
- PS2S_CODE_READY = 0x01
+ PS2S_CODE_READY = 0x01,
+ PS2S_DONT_SEND = 0x02,
+ PS2S_FROM_MOUSE = 0x20
};
enum {
- PS2G_XT_COMPAT = 0x40
+ PS2G_KBD_IRQ = 0x01,
+ PS2G_MOUSE_IRQ = 0x02,
+ PS2G_KBD_OFF = 0x10,
+ PS2G_MOUSE_OFF = 0x20,
+ PS2G_XT_COMPAT = 0x40
+};
+
+enum {
+ MFB_BUTTON_ONE = 0x01,
+ MFB_BUTTON_TWO = 0x02,
+ MFB_BUTTON_MID = 0x04,
+ MFB_X_SIGN = 0x10,
+ MFB_Y_SIGN = 0x20
+};
+
+enum {
+ MC_ENABLE_REPORT = 0xf4
};
static uint32_t n_scantabs;
@@ -55,7 +75,16 @@ void init_kbd() {
outb(PS2_CMD, PS2C_READ_CONFIG);
uint8_t config = inb(PS2_DATA);
outb(PS2_CMD, PS2C_WRITE_CONFIG);
- outb(PS2_DATA, config | PS2G_XT_COMPAT);
+ outb(PS2_DATA, (config | PS2G_XT_COMPAT | PS2G_MOUSE_IRQ | PS2G_KBD_IRQ) & ~(PS2G_MOUSE_OFF | PS2G_KBD_OFF));
+
+ outb(PS2_CMD, PS2C_SEND_AUX);
+ while (inb(PS2_CMD) & PS2S_DONT_SEND)
+ ;
+ outb(PS2_DATA, MC_ENABLE_REPORT);
+ while (!(inb(PS2_CMD) & PS2S_CODE_READY))
+ ;
+ if (inb(PS2_DATA) != 0xfa)
+ PANIC("didn't get ACK after enabling mouse reporting");
uint32_t layout_len;
if (!try_get_sz_setting("kbd-layout", scantab_path + SCANTAB_DIR_LEN, LAYOUT_NAME_MAX_LEN, &layout_len))
@@ -107,11 +136,54 @@ static inline uint8_t get_next_code_byte() {
return cb;
}
+static inline uint8_t get_wait() {
+ for (uint32_t i = 0; i < 1000000; ++i)
+ ;
+ return inb(PS2_DATA);
+}
+
static enum key_modifiers_t keymods = 0;
+bool last_mouse_one = false;
+bool last_mouse_two = false;
+bool last_mouse_mid = false;
+
enum kbd_isr_result on_kbd_isr() {
-//logf(LOG_INFO, "on_kbd_isr()");
- while (inb(PS2_CMD) & PS2S_CODE_READY) {
+ uint8_t code;
+ while ((code = inb(PS2_CMD)) & PS2S_CODE_READY) {
+ if (code & PS2S_FROM_MOUSE) {
+ const uint8_t first = get_wait();
+ const uint8_t x = get_wait();
+ const uint8_t y = get_wait();
+
+ if (x || y || (first & (MFB_X_SIGN | MFB_Y_SIGN)))
+ move_mouse_by((first & MFB_Y_SIGN) ? 256 - y : -y,
+ (first & MFB_X_SIGN) ? x - 256 : x);
+
+ const bool mouse_one = first & MFB_BUTTON_ONE;
+ const bool mouse_two = first & MFB_BUTTON_TWO;
+ const bool mouse_mid = first & MFB_BUTTON_MID;
+
+ if (mouse_one && !last_mouse_one)
+ mouse_button(LEFT, false);
+ if (mouse_two && !last_mouse_two)
+ mouse_button(RIGHT, false);
+ if (mouse_mid && !last_mouse_mid)
+ mouse_button(MIDDLE, false);
+
+ if (!mouse_one && last_mouse_one)
+ mouse_button(LEFT, true);
+ if (!mouse_two && last_mouse_two)
+ mouse_button(RIGHT, true);
+ if (!mouse_mid && last_mouse_mid)
+ mouse_button(MIDDLE, true);
+
+ last_mouse_one = mouse_one;
+ last_mouse_two = mouse_two;
+ last_mouse_mid = mouse_mid;
+ continue;
+ }
+
last_code_byte = 0;
uint8_t code[256];
uint8_t code_i = 0;
diff --git a/src/kernel/paging.c b/src/kernel/paging.c
index 0432ab6..dc7ca27 100644
--- a/src/kernel/paging.c
+++ b/src/kernel/paging.c
@@ -115,11 +115,15 @@ void init_paging() {
for (uint32_t i = 0; i < 1048576; ++i)
KPAGE_TABLE_0[i] = (i * 4096) | PE_WRITABLE | PE_PRESENT;
+ KPAGE_TABLE_0[0x00020] &= ~PE_PRESENT;
+ KPAGE_TABLE_0[0x0002f] &= ~PE_PRESENT;
for (uint16_t i = 0; i < 1024; ++i)
KPAGE_DIR[i] = (uint32_t)(KPAGE_TABLE_0 + i * 1024) | PE_WRITABLE | PE_PRESENT;
for (uint16_t i = 0; i < KERNEL_END / 4096; ++i)
kmap[i] = (i * 4096) | PE_USER | PE_PRESENT;
+ kmap[0x00020] &= ~PE_PRESENT;
+ kmap[0x0002f] &= ~PE_PRESENT;
asm volatile (
"mov $0x00005000, %%eax\n"
diff --git a/src/kernel/task.c b/src/kernel/task.c
index 93310bc..077eea6 100644
--- a/src/kernel/task.c
+++ b/src/kernel/task.c
@@ -62,11 +62,11 @@ uint32_t new_task(struct task_state state) {
static void tmp_halt() {
//logf(LOG_INFO, "scheduler halting");
- TSS->esp0 = 0x0003c000;
+ TSS->esp0 = 0x00028000;
asm("sti\n"
"hlt\n"
"cli");
- TSS->esp0 = 0x00040000;
+ TSS->esp0 = 0x0002f000;
//logf(LOG_INFO, "scheduler resumed");
}
@@ -121,7 +121,7 @@ void init_tasks() {
ipc_pipes[i].buffer = 0;
TSS->ss0 = 0x18;
- TSS->esp0 = 0x00040000;
+ TSS->esp0 = 0x0002f000;
//TSS->cs = 0x13;
//TSS->ds = 0x1b;
//TSS->ss = 0x1b;
diff --git a/src/kernel/window.c b/src/kernel/window.c
index e7cf30d..bc36578 100644
--- a/src/kernel/window.c
+++ b/src/kernel/window.c
@@ -71,6 +71,49 @@ static void load_mode_params() {
);
}
+static inline void blit_pixel(uint32_t *into, struct pixel from) {
+ *into &= pix_clear_mask;
+ *into |= (from.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off;
+ *into |= (from.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off;
+ *into |= (from.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off;
+}
+
+static uint16_t mouse_y;
+static uint16_t mouse_x;
+
+#define MOUSE_WIDTH 8
+#define MOUSE_HEIGHT 8
+
+#define B {.r = 0, .g = 0, .b = 0, .pad = 0}
+#define W {.r = 255, .g = 255, .b = 255, .pad = 0}
+#define T {.pad = 1}
+
+static const struct pixel mouse_image[] = {
+ W, W, W, W, W, W, T, T,
+ W, B, B, B, W, T, T, T,
+ W, B, B, B, W, W, T, T,
+ W, B, B, B, B, W, W, T,
+ W, W, W, B, B, B, W, T,
+ W, T, W, W, B, B, B, W,
+ T, T, T, W, W, B, W, W,
+ T, T, T, T, W, W, W, T
+};
+
+static void blit_mouse() {
+ uint16_t y_max = mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height - mouse_y : MOUSE_HEIGHT;
+ uint16_t x_max = mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width - mouse_x : MOUSE_WIDTH;
+ void *row = VBE_MODE_INFO->frame_buf + mouse_y * VBE_MODE_INFO->pitch + mouse_x * (VBE_MODE_INFO->bpp / 8);
+ for (uint16_t y = 0; y < y_max; ++y) {
+ uint32_t *out_pix = row;
+ for (uint16_t x = 0; x < x_max; ++x) {
+ if (!mouse_image[y * MOUSE_WIDTH + x].pad)
+ blit_pixel(out_pix, mouse_image[y * MOUSE_WIDTH + x]);
+ out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8);
+ }
+ row += VBE_MODE_INFO->pitch;
+ }
+}
+
static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) {
void *row = VBE_MODE_INFO->frame_buf + y_min * VBE_MODE_INFO->pitch + x_min * (VBE_MODE_INFO->bpp / 8);
const struct super_pixel *from_row = buffer + y_min * VBE_MODE_INFO->width + x_min;
@@ -78,16 +121,17 @@ static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max)
uint32_t *out_pix = row;
const struct super_pixel *from = from_row;
for (uint16_t x = x_min; x < x_max; ++x) {
- *out_pix &= pix_clear_mask;
- *out_pix |= (from->p.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off;
- *out_pix |= (from->p.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off;
- *out_pix |= (from->p.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off;
+ blit_pixel(out_pix, from->p);
out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8);
++from;
}
row += VBE_MODE_INFO->pitch;
from_row += VBE_MODE_INFO->width;
}
+
+ if ((y_min < mouse_y) && (y_max > mouse_y) &&
+ (x_min < mouse_x) && (x_max > mouse_x))
+ blit_mouse();
}
#define POWER_OFF_MESSAGE_PITCH 45
@@ -343,8 +387,6 @@ static void send_action(struct window *w, struct window_action packet) {
#define RUN_COMMAND_FILE "sys/winspace.rc"
enum wm_action {
- WM_SHUFFLE_UP,
- WM_SHUFFLE_DOWN,
WM_MOVE_LEFT,
WM_MOVE_RIGHT,
WM_MOVE_UP,
@@ -355,8 +397,6 @@ enum wm_action {
};
static struct key_packet keybinds[] = {
- {.key_id = KEY_PAGE_DOWN, .modifiers = WINS},
- {.key_id = KEY_PAGE_UP, .modifiers = WINS},
{.key_id = KEY_LEFT_ARROW, .modifiers = WINS},
{.key_id = KEY_RIGHT_ARROW, .modifiers = WINS},
{.key_id = KEY_UP_ARROW, .modifiers = WINS},
@@ -393,6 +433,10 @@ void init_win() {
paint_bg();
blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height);
+ mouse_x = (VBE_MODE_INFO->width - MOUSE_WIDTH) / 2;
+ mouse_y = (VBE_MODE_INFO->height - MOUSE_HEIGHT) / 2;
+ blit_mouse();
+
const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE);
if (!fid)
PANIC("Couldn't open " RUN_COMMAND_FILE ".");
@@ -425,34 +469,7 @@ void on_action(struct window_action packet) {
for (uint8_t i = 0; i < N_WM_ACTIONS; ++i)
if (fuzzy_key_match(keybinds[i], packet.as_key)) {
switch_to_kernel_cr3();
- struct window *old_top, *old_bottom;
switch (i) {
- case WM_SHUFFLE_UP:
- if (!top_window || !top_window->below)
- break;
- old_top = top_window;
- old_bottom = bottom_window;
- top_window = old_top->below;
- top_window->above = 0;
- old_top->below = 0;
- old_top->above = old_bottom;
- old_bottom->below = old_top;
- bottom_window = old_top;
- paint_and_above(bottom_window->above);
- break;
- case WM_SHUFFLE_DOWN:
- if (!top_window || !top_window->below)
- break;
- old_top = top_window;
- old_bottom = bottom_window;
- bottom_window = old_bottom->above;
- bottom_window->below = 0;
- old_bottom->above = 0;
- old_bottom->below = old_top;
- old_top->above = old_bottom;
- top_window = old_bottom;
- paint_and_above(top_window);
- break;
case WM_MOVE_LEFT:
if (top_window) {
top_window->xpos -= MOVE_BY;
@@ -487,4 +504,48 @@ void on_action(struct window_action packet) {
if (top_window)
send_action(top_window, packet);
+}
+
+void move_mouse_by(int16_t y, int16_t x) {
+//logf(LOG_INFO, "old mouse coords: (%d, %d)", mouse_x, mouse_y);
+ switch_to_kernel_cr3();
+ blit(mouse_x, mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width : mouse_x + MOUSE_WIDTH,
+ mouse_y, mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height : mouse_y + MOUSE_HEIGHT);
+ mouse_y = (-y > mouse_y) ? 0 : (y + mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height) ? VBE_MODE_INFO->height - MOUSE_HEIGHT : y + mouse_y;
+ mouse_x = (-x > mouse_x) ? 0 : (x + mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width) ? VBE_MODE_INFO->width - MOUSE_WIDTH : x + mouse_x;
+ blit_mouse();
+ switch_to_task_cr3();
+//logf(LOG_INFO, "new mouse coords: (%d, %d)", mouse_x, mouse_y);
+}
+
+static void focus(struct window *w) {
+ send_action(top_window, (struct window_action){.action_type = FOCUS_LEAVE});
+
+ if (w->below)
+ w->below->above = w->above;
+ else
+ bottom_window = w->above;
+ w->above->below = w->below;
+ w->above = 0;
+ w->below = top_window;
+ top_window->above = w;
+ top_window = w;
+
+ send_action(w, (struct window_action){.action_type = FOCUS_ENTER});
+}
+
+void mouse_button(enum mouse_button which, bool up) {
+ if (!top_window)
+ return;
+
+ struct window *const clicked_on = buffer[mouse_y * VBE_MODE_INFO->width + mouse_x].from_window;
+ if (!clicked_on)
+ return;
+
+ if (clicked_on != top_window) {
+ focus(clicked_on);
+ paint_and_above(clicked_on);
+ }
+
+ send_action(clicked_on, (struct window_action){.action_type = up ? MOUSE_UP : MOUSE_DOWN, .as_mouse = {.y = mouse_y - clicked_on->ypos, .x = mouse_x - clicked_on->xpos, .which = which}});
} \ No newline at end of file
diff --git a/src/kernel/window.h b/src/kernel/window.h
index 0a83845..a1f9716 100644
--- a/src/kernel/window.h
+++ b/src/kernel/window.h
@@ -33,4 +33,7 @@ void delete_any_windows_from(struct task_state *tstate);
void show_shutdown();
+void move_mouse_by(int16_t y, int16_t x);
+void mouse_button(enum mouse_button which, bool up);
+
#endif