mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
Stage 15
This commit is contained in:
1
Makefile
1
Makefile
@@ -85,6 +85,7 @@ C_SOURCES := \
|
|||||||
clks/kernel/tty.c \
|
clks/kernel/tty.c \
|
||||||
clks/kernel/pmm.c \
|
clks/kernel/pmm.c \
|
||||||
clks/kernel/heap.c \
|
clks/kernel/heap.c \
|
||||||
|
clks/kernel/keyboard.c \
|
||||||
clks/kernel/interrupts.c \
|
clks/kernel/interrupts.c \
|
||||||
clks/kernel/scheduler.c \
|
clks/kernel/scheduler.c \
|
||||||
clks/kernel/elf64.c \
|
clks/kernel/elf64.c \
|
||||||
|
|||||||
10
clks/include/clks/keyboard.h
Normal file
10
clks/include/clks/keyboard.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef CLKS_KEYBOARD_H
|
||||||
|
#define CLKS_KEYBOARD_H
|
||||||
|
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
void clks_keyboard_init(void);
|
||||||
|
void clks_keyboard_handle_scancode(u8 scancode);
|
||||||
|
u64 clks_keyboard_hotkey_switch_count(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <clks/cpu.h>
|
#include <clks/cpu.h>
|
||||||
#include <clks/interrupts.h>
|
#include <clks/interrupts.h>
|
||||||
#include <clks/log.h>
|
#include <clks/log.h>
|
||||||
|
#include <clks/keyboard.h>
|
||||||
#include <clks/scheduler.h>
|
#include <clks/scheduler.h>
|
||||||
#include <clks/syscall.h>
|
#include <clks/syscall.h>
|
||||||
#include <clks/types.h>
|
#include <clks/types.h>
|
||||||
@@ -18,9 +19,13 @@
|
|||||||
|
|
||||||
#define CLKS_IRQ_BASE 32U
|
#define CLKS_IRQ_BASE 32U
|
||||||
#define CLKS_IRQ_TIMER 32U
|
#define CLKS_IRQ_TIMER 32U
|
||||||
|
#define CLKS_IRQ_KEYBOARD 33U
|
||||||
#define CLKS_IRQ_LAST 47U
|
#define CLKS_IRQ_LAST 47U
|
||||||
#define CLKS_SYSCALL_VECTOR 128U
|
#define CLKS_SYSCALL_VECTOR 128U
|
||||||
|
|
||||||
|
#define CLKS_PS2_DATA_PORT 0x60U
|
||||||
|
#define CLKS_PS2_STATUS_PORT 0x64U
|
||||||
|
|
||||||
struct clks_idt_entry {
|
struct clks_idt_entry {
|
||||||
u16 offset_low;
|
u16 offset_low;
|
||||||
u16 selector;
|
u16 selector;
|
||||||
@@ -192,7 +197,7 @@ static void clks_pic_remap_and_mask(void) {
|
|||||||
(void)master_mask;
|
(void)master_mask;
|
||||||
(void)slave_mask;
|
(void)slave_mask;
|
||||||
|
|
||||||
clks_outb(CLKS_PIC1_DATA, 0xFEU);
|
clks_outb(CLKS_PIC1_DATA, 0xFCU);
|
||||||
clks_outb(CLKS_PIC2_DATA, 0xFFU);
|
clks_outb(CLKS_PIC2_DATA, 0xFFU);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +230,10 @@ static void clks_load_idt(void) {
|
|||||||
__asm__ volatile("lidt %0" : : "m"(idtr));
|
__asm__ volatile("lidt %0" : : "m"(idtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static clks_bool clks_ps2_has_output(void) {
|
||||||
|
return (clks_inb(CLKS_PS2_STATUS_PORT) & 0x01U) != 0U ? CLKS_TRUE : CLKS_FALSE;
|
||||||
|
}
|
||||||
static void clks_enable_interrupts(void) {
|
static void clks_enable_interrupts(void) {
|
||||||
__asm__ volatile("sti");
|
__asm__ volatile("sti");
|
||||||
}
|
}
|
||||||
@@ -248,6 +257,11 @@ void clks_interrupt_dispatch(struct clks_interrupt_frame *frame) {
|
|||||||
if (vector == CLKS_IRQ_TIMER) {
|
if (vector == CLKS_IRQ_TIMER) {
|
||||||
clks_timer_ticks++;
|
clks_timer_ticks++;
|
||||||
clks_scheduler_on_timer_tick(clks_timer_ticks);
|
clks_scheduler_on_timer_tick(clks_timer_ticks);
|
||||||
|
} else if (vector == CLKS_IRQ_KEYBOARD) {
|
||||||
|
if (clks_ps2_has_output() == CLKS_TRUE) {
|
||||||
|
u8 scancode = clks_inb(CLKS_PS2_DATA_PORT);
|
||||||
|
clks_keyboard_handle_scancode(scancode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vector >= CLKS_IRQ_BASE && vector <= CLKS_IRQ_LAST) {
|
if (vector >= CLKS_IRQ_BASE && vector <= CLKS_IRQ_LAST) {
|
||||||
@@ -323,4 +337,4 @@ void clks_interrupts_init(void) {
|
|||||||
|
|
||||||
u64 clks_interrupts_timer_ticks(void) {
|
u64 clks_interrupts_timer_ticks(void) {
|
||||||
return clks_timer_ticks;
|
return clks_timer_ticks;
|
||||||
}
|
}
|
||||||
|
|||||||
53
clks/kernel/keyboard.c
Normal file
53
clks/kernel/keyboard.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include <clks/keyboard.h>
|
||||||
|
#include <clks/log.h>
|
||||||
|
#include <clks/tty.h>
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
#define CLKS_SC_ALT 0x38U
|
||||||
|
#define CLKS_SC_F1 0x3BU
|
||||||
|
#define CLKS_SC_F2 0x3CU
|
||||||
|
#define CLKS_SC_F3 0x3DU
|
||||||
|
#define CLKS_SC_F4 0x3EU
|
||||||
|
|
||||||
|
static clks_bool clks_kbd_alt_down = CLKS_FALSE;
|
||||||
|
static u64 clks_kbd_hotkey_switches = 0ULL;
|
||||||
|
|
||||||
|
void clks_keyboard_init(void) {
|
||||||
|
clks_kbd_alt_down = CLKS_FALSE;
|
||||||
|
clks_kbd_hotkey_switches = 0ULL;
|
||||||
|
clks_log(CLKS_LOG_INFO, "KBD", "ALT+F1..F4 TTY HOTKEY ONLINE");
|
||||||
|
}
|
||||||
|
|
||||||
|
void clks_keyboard_handle_scancode(u8 scancode) {
|
||||||
|
clks_bool released = ((scancode & 0x80U) != 0U) ? CLKS_TRUE : CLKS_FALSE;
|
||||||
|
u8 code = (u8)(scancode & 0x7FU);
|
||||||
|
|
||||||
|
if (code == CLKS_SC_ALT) {
|
||||||
|
clks_kbd_alt_down = (released == CLKS_FALSE) ? CLKS_TRUE : CLKS_FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (released == CLKS_TRUE || clks_kbd_alt_down == CLKS_FALSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code >= CLKS_SC_F1 && code <= CLKS_SC_F4) {
|
||||||
|
u32 target = (u32)(code - CLKS_SC_F1);
|
||||||
|
u32 before = clks_tty_active();
|
||||||
|
u32 after;
|
||||||
|
|
||||||
|
clks_tty_switch(target);
|
||||||
|
after = clks_tty_active();
|
||||||
|
|
||||||
|
if (after != before) {
|
||||||
|
clks_kbd_hotkey_switches++;
|
||||||
|
clks_log(CLKS_LOG_INFO, "TTY", "HOTKEY SWITCH");
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "TTY", "ACTIVE", (u64)after);
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "TTY", "HOTKEY_SWITCHES", clks_kbd_hotkey_switches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 clks_keyboard_hotkey_switch_count(void) {
|
||||||
|
return clks_kbd_hotkey_switches;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <clks/fs.h>
|
#include <clks/fs.h>
|
||||||
#include <clks/heap.h>
|
#include <clks/heap.h>
|
||||||
#include <clks/interrupts.h>
|
#include <clks/interrupts.h>
|
||||||
|
#include <clks/keyboard.h>
|
||||||
#include <clks/kelf.h>
|
#include <clks/kelf.h>
|
||||||
#include <clks/kernel.h>
|
#include <clks/kernel.h>
|
||||||
#include <clks/log.h>
|
#include <clks/log.h>
|
||||||
@@ -63,7 +64,7 @@ static void clks_task_usrd(u64 tick) {
|
|||||||
clks_userland_tick(tick);
|
clks_userland_tick(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clks_stage14_syscall_probe(void) {
|
static void clks_stage15_syscall_probe(void) {
|
||||||
char child_name[96];
|
char child_name[96];
|
||||||
char read_buf[160];
|
char read_buf[160];
|
||||||
u64 root_children;
|
u64 root_children;
|
||||||
@@ -170,7 +171,7 @@ void clks_kernel_main(void) {
|
|||||||
clks_tty_init();
|
clks_tty_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE14 START");
|
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE15 START");
|
||||||
|
|
||||||
if (boot_fb == CLKS_NULL) {
|
if (boot_fb == CLKS_NULL) {
|
||||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||||
@@ -233,6 +234,7 @@ void clks_kernel_main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clks_exec_init();
|
clks_exec_init();
|
||||||
|
clks_keyboard_init();
|
||||||
|
|
||||||
if (clks_userland_init() == CLKS_FALSE) {
|
if (clks_userland_init() == CLKS_FALSE) {
|
||||||
clks_log(CLKS_LOG_ERROR, "USER", "USERLAND INIT FAILED");
|
clks_log(CLKS_LOG_ERROR, "USER", "USERLAND INIT FAILED");
|
||||||
@@ -279,11 +281,10 @@ void clks_kernel_main(void) {
|
|||||||
syscall_ticks = clks_syscall_invoke_kernel(CLKS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
|
syscall_ticks = clks_syscall_invoke_kernel(CLKS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
|
||||||
clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks);
|
clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks);
|
||||||
|
|
||||||
clks_stage14_syscall_probe();
|
clks_stage15_syscall_probe();
|
||||||
|
|
||||||
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
|
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
|
||||||
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
|
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
|
||||||
|
|
||||||
clks_cpu_halt_forever();
|
clks_cpu_halt_forever();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
53
docs/stage15.md
Normal file
53
docs/stage15.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# CLeonOS Stage15
|
||||||
|
|
||||||
|
## Stage Goal
|
||||||
|
- Keep ELF path unchanged and continue non-ELF stability work.
|
||||||
|
- Add PS/2 keyboard IRQ handling in kernel interrupt path.
|
||||||
|
- Support virtual terminal hotkey switching with `Alt+F1`~`Alt+F4`.
|
||||||
|
- Keep scheduler, syscall, and existing Stage14 behavior stable.
|
||||||
|
|
||||||
|
## What Was Implemented
|
||||||
|
- New keyboard module:
|
||||||
|
- `clks/include/clks/keyboard.h`
|
||||||
|
- `clks/kernel/keyboard.c`
|
||||||
|
- Interrupt integration:
|
||||||
|
- Enable IRQ1 (keyboard) alongside IRQ0 in PIC mask.
|
||||||
|
- Read scancode from PS/2 data port `0x60`.
|
||||||
|
- Dispatch scancode to keyboard hotkey handler.
|
||||||
|
- Hotkey behavior:
|
||||||
|
- Hold `Alt` + press `F1/F2/F3/F4` to switch TTY 0/1/2/3.
|
||||||
|
- On successful switch, kernel logs active TTY and switch counter.
|
||||||
|
- Boot stage update:
|
||||||
|
- `CLEONOS STAGE15 START`.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- Kernel boots and prints `CLEONOS STAGE15 START`.
|
||||||
|
- Boot logs include keyboard module online message:
|
||||||
|
- `[INFO][KBD] ALT+F1..F4 TTY HOTKEY ONLINE`
|
||||||
|
- In QEMU runtime:
|
||||||
|
- Press `Alt+F2` / `Alt+F3` / `Alt+F4` / `Alt+F1`.
|
||||||
|
- Logs show:
|
||||||
|
- `[INFO][TTY] HOTKEY SWITCH`
|
||||||
|
- `[INFO][TTY] ACTIVE: 0X...`
|
||||||
|
- `[INFO][TTY] HOTKEY_SWITCHES: 0X...`
|
||||||
|
|
||||||
|
## Build Targets
|
||||||
|
- `make setup`
|
||||||
|
- `make userapps`
|
||||||
|
- `make iso`
|
||||||
|
- `make run`
|
||||||
|
- `make debug`
|
||||||
|
|
||||||
|
## QEMU Command
|
||||||
|
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
|
||||||
|
|
||||||
|
## Common Bugs and Debugging
|
||||||
|
- Hotkey has no effect:
|
||||||
|
- Verify QEMU window is focused and keyboard input is captured.
|
||||||
|
- Confirm logs show Stage15 keyboard online message.
|
||||||
|
- IRQ timer works but keyboard does not:
|
||||||
|
- Re-check PIC mask includes IRQ1 (master mask should allow IRQ0 and IRQ1).
|
||||||
|
- Wrong function key mapping:
|
||||||
|
- Current mapping is Set1 scancode: F1=0x3B, F2=0x3C, F3=0x3D, F4=0x3E.
|
||||||
|
- Excessive hotkey logs:
|
||||||
|
- Holding key may repeat make scancode by keyboard auto-repeat; this is expected in current stage.
|
||||||
Reference in New Issue
Block a user