removed pdclib, strange things were happening..., user shell kinda works now
This commit is contained in:
@@ -33,7 +33,7 @@ init_pic:
|
||||
outb %al, $PIC2_DATA
|
||||
|
||||
# mask
|
||||
mov $0xFE, %al
|
||||
mov $0xF8, %al
|
||||
outb %al, $PIC1_DATA
|
||||
mov $0xFF, %al
|
||||
outb %al, $PIC2_DATA
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
|
||||
#include <drivers/ps2/ps2.h>
|
||||
|
||||
static const char scancode_to_ascii[] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
|
||||
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
|
||||
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0,
|
||||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' '
|
||||
};
|
||||
|
||||
extern void ps2_wait_input_empty(void);
|
||||
extern void ps2_wait_output_full(void);
|
||||
extern void ps2_write_command(uint8_t);
|
||||
extern uint8_t ps2_read_data(void);
|
||||
extern void ps2_write_data(uint8_t);
|
||||
extern void ps2_flush_output_buffer(void);
|
||||
|
||||
extern void io_wait(void);
|
||||
|
||||
static uint8_t read_ccb() {
|
||||
@@ -68,4 +73,19 @@ int init_ps2() {
|
||||
write_ccb(ccb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char ps2_get_ascii(uint8_t scancode) {
|
||||
if (scancode & 0x80) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scancode < sizeof(scancode_to_ascii)) {
|
||||
char ascii = scancode_to_ascii[scancode];
|
||||
if (ascii != 0) {
|
||||
return ascii;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -18,8 +18,11 @@
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdint.h>
|
||||
|
||||
int init_ps2();
|
||||
uint8_t ps2_read_data();
|
||||
|
||||
char ps2_get_ascii(uint8_t scancode);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
#include <lib/print.h>
|
||||
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "kbd.h"
|
||||
#include "syscall.h"
|
||||
#include "common.h"
|
||||
#include "gdt.h"
|
||||
@@ -144,6 +143,11 @@ void common_interrupt_handler(intr_regs_t *args) {
|
||||
kprintf("Current cr3: 0x%x\n", fetch_cr3());
|
||||
if (args->cs == 0x1b) {
|
||||
kprintf("User ESP: 0x%x\n", args->u_esp);
|
||||
kprintf("ESP: 0x%x\t0x%x\t0x%x\t0x%x\n",
|
||||
*(uint32_t*)args->u_esp,
|
||||
*(uint32_t*)(args->u_esp + 4),
|
||||
*(uint32_t*)(args->u_esp + 8),
|
||||
*(uint32_t*)(args->u_esp + 12));
|
||||
kprintf("User SS: 0x%x\n", args->u_ss);
|
||||
}
|
||||
kprintf("Caused by: %s, %s, running in %s mode\n",
|
||||
@@ -158,8 +162,11 @@ void common_interrupt_handler(intr_regs_t *args) {
|
||||
break;
|
||||
}
|
||||
case 33: {
|
||||
kprintf("ps2 keyboard interrupt\n");
|
||||
uint8_t data = ps2_read_data();
|
||||
char ascii = ps2_get_ascii(data);
|
||||
if (ascii != 0) {
|
||||
kbd_push(ascii);
|
||||
}
|
||||
send_eoi_master();
|
||||
break;
|
||||
}
|
||||
|
||||
84
kernel/kbd.c
Normal file
84
kernel/kbd.c
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "kbd.h"
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <lib/tasks.h>
|
||||
#include <lib/print.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define KBD_BUFFER_SIZE 256
|
||||
|
||||
static spinlock_t kbd_lock = {0};
|
||||
static process_t* kbd_waiting_task = NULL;
|
||||
|
||||
static char kbd_buffer[KBD_BUFFER_SIZE];
|
||||
static int kbd_head = 0;
|
||||
static int kbd_tail = 0;
|
||||
|
||||
static void lock_kbd() {
|
||||
disable_interrupts();
|
||||
spin_lock(&kbd_lock);
|
||||
}
|
||||
|
||||
static void unlock_kbd() {
|
||||
spin_unlock(&kbd_lock);
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
static void kbd_set_waiting(process_t* task) {
|
||||
lock_kbd();
|
||||
if (kbd_head == kbd_tail) {
|
||||
kbd_waiting_task = task;
|
||||
}
|
||||
unlock_kbd();
|
||||
}
|
||||
|
||||
static char kbd_pop() {
|
||||
char c = 0;
|
||||
lock_kbd();
|
||||
if (kbd_head != kbd_tail) {
|
||||
c = kbd_buffer[kbd_tail];
|
||||
kbd_tail = (kbd_tail + 1) % KBD_BUFFER_SIZE;
|
||||
}
|
||||
unlock_kbd();
|
||||
return c;
|
||||
}
|
||||
|
||||
void kbd_push(char c) {
|
||||
spin_lock(&kbd_lock);
|
||||
// push to buffer first, very important
|
||||
int next_head = (kbd_head + 1) % KBD_BUFFER_SIZE;
|
||||
if (next_head != kbd_tail) {
|
||||
kbd_buffer[kbd_head] = c;
|
||||
kbd_head = next_head;
|
||||
}
|
||||
|
||||
if (kbd_waiting_task != NULL) {
|
||||
wake(kbd_waiting_task);
|
||||
kbd_waiting_task = NULL;
|
||||
}
|
||||
spin_unlock(&kbd_lock);
|
||||
}
|
||||
|
||||
int kbd_ready() {
|
||||
int ready = 0;
|
||||
lock_kbd();
|
||||
ready = (kbd_head != kbd_tail);
|
||||
unlock_kbd();
|
||||
return ready;
|
||||
}
|
||||
|
||||
void kbd_wait() {
|
||||
process_t* task = current_task();
|
||||
while (!kbd_ready()) {
|
||||
task->state = STATE_BLOCKED;
|
||||
kbd_set_waiting(task);
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
char kbd_read() {
|
||||
return kbd_pop();
|
||||
}
|
||||
6
kernel/kbd.h
Normal file
6
kernel/kbd.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
char kbd_read();
|
||||
void kbd_push(char c);
|
||||
int kbd_ready();
|
||||
void kbd_wait();
|
||||
@@ -57,6 +57,7 @@ vfs_node_t* load_initrd() {
|
||||
}
|
||||
|
||||
void load_root_program(const char* path) {
|
||||
disable_interrupts();
|
||||
uint32_t kernel_cr3 = fetch_cr3();
|
||||
void* cr3 = create_task_pd();
|
||||
load_pd(cr3);
|
||||
@@ -129,6 +130,7 @@ void load_root_program(const char* path) {
|
||||
*(--u_esp) = 0; // argc = 0
|
||||
|
||||
create_task(e_hdr->e_entry, (uint32_t)cr3, 1, (uint32_t)u_esp);
|
||||
enable_interrupts();
|
||||
|
||||
load_pd((void*)kernel_cr3);
|
||||
flush_tlb();
|
||||
@@ -169,7 +171,8 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
|
||||
disable_interrupts();
|
||||
init_scheduler();
|
||||
load_root_program("/origin.elf");
|
||||
kprintf("done loading origin program\n");
|
||||
enable_interrupts();
|
||||
|
||||
kprintf("loading rocksh...\n");
|
||||
load_root_program("/rocksh.elf");
|
||||
}
|
||||
|
||||
@@ -80,6 +80,11 @@ void kprintf(const char* fmt, ...) {
|
||||
kputx(x);
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
int c = va_arg(args, int);
|
||||
vga_putchar((char)c);
|
||||
break;
|
||||
}
|
||||
case '%':
|
||||
vga_putchar('%');
|
||||
break;
|
||||
|
||||
@@ -6,24 +6,31 @@
|
||||
yield: # void yield()
|
||||
cli
|
||||
|
||||
pushfl
|
||||
pushl %cs
|
||||
popl %ecx
|
||||
|
||||
pushfl // EFLAGS
|
||||
pushl %cs // CS
|
||||
pushl %ecx // EIP
|
||||
|
||||
movl 8(%esp), %eax
|
||||
pushal
|
||||
call send_eoi_master
|
||||
|
||||
xor %eax, %eax
|
||||
mov %ds, %ax
|
||||
pushl %eax
|
||||
|
||||
movl 4(%esp), %ebx # Get CS
|
||||
movl %ebx, 8(%esp) # Move CS over Old EIP
|
||||
movl 0(%esp), %ebx # Get Return EIP
|
||||
movl %ebx, 4(%esp) # Move Return EIP over CS
|
||||
addl $4, %esp # Adjust stack pointer up.
|
||||
|
||||
pushal
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
|
||||
pushl %esp
|
||||
call switch_context
|
||||
movl %eax, %esp
|
||||
|
||||
popl %eax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
|
||||
popal
|
||||
sti
|
||||
iret
|
||||
@@ -149,10 +149,16 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp) {
|
||||
}
|
||||
|
||||
process_t* current_task() {
|
||||
lock_scheduler();
|
||||
process_t* rtn = &process_table[current_process];
|
||||
unlock_scheduler();
|
||||
return rtn;
|
||||
}
|
||||
|
||||
process_t* current_task_unsafe() {
|
||||
return &process_table[current_process];
|
||||
}
|
||||
|
||||
void sleep(uint32_t ms) {
|
||||
if (ms == 0) return;
|
||||
lock_scheduler();
|
||||
@@ -169,3 +175,10 @@ void exit() {
|
||||
unlock_scheduler();
|
||||
}
|
||||
|
||||
void wake(process_t* task) {
|
||||
lock_scheduler();
|
||||
if (task->state == STATE_SLEEPING || task->state == STATE_BLOCKED) {
|
||||
task->state = STATE_READY;
|
||||
}
|
||||
unlock_scheduler();
|
||||
}
|
||||
@@ -12,5 +12,6 @@ process_t* current_task();
|
||||
void sleep(uint32_t ms);
|
||||
void yield();
|
||||
void exit();
|
||||
void wake(process_t* task);
|
||||
|
||||
#endif
|
||||
@@ -4,22 +4,18 @@
|
||||
#include "memory/mm.h"
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "kbd.h"
|
||||
|
||||
#include <drivers/vga/vga.h>
|
||||
|
||||
#include <lib/print.h>
|
||||
|
||||
typedef struct registers {
|
||||
uint32_t gs, fs, es, ds; // Pushed manually
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
|
||||
uint32_t int_no, err_code; // Pushed manually
|
||||
uint32_t eip, cs, eflags, useresp, ss; // Pushed automatically by CPU
|
||||
} registers_t;
|
||||
|
||||
|
||||
static int32_t sys_exit(int status) {
|
||||
asm volatile("cli");
|
||||
asm volatile("hlt");
|
||||
process_t* task = current_task();
|
||||
task->state = STATE_DEAD;
|
||||
kprintf("Process %d exited with status %d\n", task->pid, status);
|
||||
exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -35,13 +31,18 @@ static int32_t sys_write(int fd, const void* buf, size_t count) {
|
||||
}
|
||||
|
||||
static int32_t sys_read(int fd, void* buf, size_t count) {
|
||||
if (fd == 0) { // stdin
|
||||
if (fd == 0) {
|
||||
char* cbuf = (char*)buf;
|
||||
size_t bytes_read = 0;
|
||||
|
||||
while (bytes_read < count) {
|
||||
char c = 'r';
|
||||
cbuf[bytes_read++] = c;
|
||||
if (c == '\n') break;
|
||||
kbd_wait();
|
||||
|
||||
if (kbd_ready()) {
|
||||
char c = kbd_read();
|
||||
cbuf[bytes_read++] = c;
|
||||
if (c == '\n') break;
|
||||
}
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
@@ -83,6 +84,12 @@ static int32_t sys_brk(uint32_t new_break) {
|
||||
return current->heap_end;
|
||||
}
|
||||
|
||||
typedef struct registers {
|
||||
uint32_t gs, fs, es, ds; // Pushed manually
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
|
||||
uint32_t int_no, err_code; // Pushed manually
|
||||
uint32_t eip, cs, eflags, useresp, ss; // Pushed automatically by CPU
|
||||
} registers_t;
|
||||
int32_t syscall(registers_t* regs) {
|
||||
switch(regs->eax) {
|
||||
case 1: return sys_exit(regs->ebx);
|
||||
|
||||
Reference in New Issue
Block a user