Added IRQs and little refactor :3

This commit is contained in:
vanten-s 2024-08-09 23:16:20 +02:00
parent cac521ded0
commit ddb45b819b
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
15 changed files with 284 additions and 229 deletions

View file

@ -22,14 +22,17 @@ KERNEL_OBJS=\
kernel/kernel.o \
kernel/debugging.o \
kernel/elf.o \
kernel/keyboard.o \
LIB_OBJS=\
$(ARCHDIR)/bootstrap.o \
$(ARCHDIR)/tty.o \
$(ARCHDIR)/strlib.o \
$(ARCHDIR)/idt.o \
$(ARCHDIR)/interrupt.o \
$(ARCHDIR)/interrupts/idt.o \
$(ARCHDIR)/interrupts/interrupt.o \
$(ARCHDIR)/gdt.o \
$(ARCHDIR)/userland.o \
$(ARCHDIR)/interrupts/pic.o \
OBJS=$(KERNEL_OBJS) $(LIB_OBJS)
@ -50,7 +53,7 @@ clean:
rm -f myos.iso
rm -f isodir/boot/myos.kernel
$(ARCHDIR)/interrupt.o: CFLAGS += -mgeneral-regs-only
$(ARCHDIR)/interrupts/interrupt.o: CFLAGS += -mgeneral-regs-only
# kernel/elf.o: CFLAGS += -masm=intel
%.o : %.c

View file

@ -4,7 +4,16 @@
#include "interrupt.h"
#include <stdint.h>
#include <stddef.h>
#include "io.h"
#include "../io.h"
#define IRQ0 0x20
#define IRQ1 (IRQ0 + 1)
#define IRQ2 (IRQ0 + 2)
#define IRQ3 (IRQ0 + 3)
#define IRQ4 (IRQ0 + 4)
#define IRQ5 (IRQ0 + 5)
#define IRQ6 (IRQ0 + 6)
#define IRQ7 (IRQ0 + 7)
#define NUM_ENTRIES 0x100
@ -104,7 +113,6 @@ struct InterruptDescriptor generate_entry(bool present, void isr(struct interrup
void idt_init()
{
terminal_initialize();
struct InterruptDescriptor entry;
entry = generate_entry(true, exception, 0xF, 0, 0x8);
@ -122,18 +130,20 @@ void idt_init()
entry = generate_entry(true, double_fault, 0xF, 0, 0x8);
add_entry(entry, DoubleFault);
outb(0x21,0x20); // Tell the PIC to use interrupts 0x20 - 0x27
entry = generate_entry(true, irq, 0xE, 0, 0x8);
for (int i = 0x20; i < 0x28; i++)
for (int i = IRQ0; i <= IRQ7; i++)
{
add_entry(entry, i);
}
entry = generate_entry(true, keyboard_interrupt, 0xE, 0, 0x8);
add_entry(entry, IRQ1);
struct InterruptDescriptor print_entry;
print_entry.present = true;
print_entry.offset = (uint32_t)print;
print_entry.gate_type = 0xE;
print_entry.ring = 0;
print_entry.ring = 3;
print_entry.selector = 0x8;
add_entry(print_entry, 0x80);
@ -142,7 +152,7 @@ void idt_init()
input_entry.present = true;
input_entry.offset = (uint32_t)input;
input_entry.gate_type = 0xE;
input_entry.ring = 0;
input_entry.ring = 3;
input_entry.selector = 0x8;
add_entry(input_entry, 0x81);

View file

@ -1,7 +1,8 @@
#include <kernel/tty.h>
#include <stddef.h>
#include <debugging.h>
#include "io.h"
#include <kernel/keyboard.h>
#include "../io.h"
struct interrupt_frame {
uint32_t eflags;
@ -45,38 +46,14 @@ __attribute__((interrupt)) void double_fault(struct interrupt_frame* frame)
__attribute__((interrupt)) void exception(struct interrupt_frame* frame)
{
terminal_writestring("Some weird error code stuff\n");
/* terminal_writestring("Error code:\n");
print_hex_bytes(frame, sizeof(frame));
terminal_putchar('\n'); */
while (1) { }
}
__attribute__((interrupt)) void print(struct interrupt_frame* frame)
{
/* terminal_initialize();
terminal_putchar(test);
test++; */
char* start;
asm("mov %%edx, %0" : "=r" (start));
terminal_writestring(start);
/* uint8_t* stack;
asm("mov %%esp, %0" : "=r" (stack));
terminal_writestring("\nSTACK:\n");
print_hex_bytes(stack - 24, 4);
terminal_putchar('\n');
print_hex_bytes(stack - 20, 4);
terminal_putchar('\n');
print_hex_bytes(stack - 16, 4);
terminal_putchar('\n');
print_hex_bytes(stack - 12, 4);
terminal_putchar('\n');
print_hex_bytes(stack - 8, 4);
terminal_putchar('\n');
print_hex_bytes(stack - 4, 4);
terminal_putchar('\n'); */
}
__attribute__((interrupt)) void input(struct interrupt_frame* frame)
@ -84,7 +61,7 @@ __attribute__((interrupt)) void input(struct interrupt_frame* frame)
char* buffer;
asm("mov %%edx, %0" : "=r" (buffer));
size_t index = 0;
/* size_t index = 0;
char current_character = get_last_key_pressed();
while (current_character != '\n') {
@ -96,12 +73,18 @@ __attribute__((interrupt)) void input(struct interrupt_frame* frame)
}
current_character = tmp;
}
buffer[index] = '\0';
buffer[index] = '\0'; */
}
__attribute__((interrupt)) void keyboard_interrupt(struct interrupt_frame* frame)
{
uint8_t scancode = inb(0x60);
handle_keyboard(scancode);
outb(0x20, 0x20);
}
__attribute__((interrupt)) void irq(struct interrupt_frame* frame)
{
terminal_writestring("Test");
outb(0x20, 0x20);
}

View file

@ -9,4 +9,5 @@ __attribute__((interrupt)) void exception(struct interrupt_frame* frame);
__attribute__((interrupt)) void print(struct interrupt_frame* frame);
__attribute__((interrupt)) void input(struct interrupt_frame* frame);
__attribute__((interrupt)) void keyboard_interrupt(struct interrupt_frame* frame);
__attribute__((interrupt)) void irq(struct interrupt_frame* frame);

View file

@ -0,0 +1,49 @@
#include "../io.h"
#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
void init_pic() {
uint8_t a1, a2;
a1 = inb(PIC1_DATA); // save masks
a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode)
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, 0x20); // ICW2: Master PIC vector offset
io_wait();
outb(PIC2_DATA, 0xFF); // ICW2: Slave PIC vector offset
io_wait();
outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
io_wait();
outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
io_wait();
outb(PIC1_DATA, ICW4_8086); // ICW4: have the PICs use 8086 mode (and not 8080 mode)
io_wait();
outb(PIC2_DATA, ICW4_8086);
io_wait();
outb(PIC1_DATA, a1); // restore saved masks.
// outb(PIC2_DATA, a2);
outb(PIC2_DATA, 0xFF);
}

View file

@ -3,17 +3,19 @@
static inline void outb(uint16_t port, uint8_t val)
{
__asm__ volatile ( "outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
* The outb %al, %dx encoding is the only option for all other cases.
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
}
static inline void inb(uint16_t port, uint8_t val)
static inline uint8_t inb(uint16_t port)
{
__asm__ volatile ( "inb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
* The outb %al, %dx encoding is the only option for all other cases.
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
uint8_t ret;
__asm__ volatile ( "inb %w1, %b0"
: "=a"(ret)
: "Nd"(port)
: "memory");
return ret;
}
static inline void io_wait(void)
{
outb(0x80, 0);
}

View file

@ -1,17 +0,0 @@
#include "io.h"
#define ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
void init_pic() {
}

View file

16
arch/i686/userland.s Normal file
View file

@ -0,0 +1,16 @@
.global jump_to_userspace
jump_to_userspace:
mov $0x20 | 0x3, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
pushl $0x20 | 0x3 /* SS*/
pushl $0x00c00100 /* ESP */
pushf /* EFLAGS */
popl %eax
orl $0x200, %eax
pushl %eax /* Set interrupts */
pushl $0x18 | 0x3 /* CS */
pushl $0x00800000 /* EIP */
iret

View file

@ -0,0 +1,3 @@
#include <stdint.h>
void handle_keyboard(uint8_t scancode);

1
include/kernel/pic.h Normal file
View file

@ -0,0 +1 @@
void init_pic();

View file

@ -3,133 +3,6 @@
#include <stdbool.h>
#include <strlib.h>
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
__asm__ volatile ( "inb %w1, %b0"
: "=a"(ret)
: "Nd"(port)
: "memory");
return ret;
}
static bool is_in_shift;
static unsigned char keyboard_char(unsigned char scancode)
{
if (0x01 < scancode && scancode < 0x0B) {
return scancode - 2 + '1';
}
if (scancode == 0x0B) {
return '0';
}
switch (scancode) {
case 0x10:
return 'Q';
case 0x11:
return 'W';
case 0x12:
return 'E';
case 0x13:
return 'R';
case 0x14:
return 'T';
case 0x15:
return 'Y';
case 0x16:
return 'U';
case 0x17:
return 'I';
case 0x18:
return 'O';
case 0x19:
return 'P';
case 0x1a:
return '[';
case 0x1b:
return ']';
case 0x1c:
return '\n';
case 0x1d:
return '\b';
case 0x1e:
return 'A';
case 0x1f:
return 'S';
case 0x20:
return 'D';
case 0x21:
return 'F';
case 0x22:
return 'G';
case 0x23:
return 'H';
case 0x24:
return 'J';
case 0x25:
return 'K';
case 0x26:
return 'L';
case 0x27:
return ';';
case 0x28:
return '\'';
case 0x29:
return '`';
case 0x2a:
is_in_shift = true;
break;
case 0x2b:
return '\\';
case 0x2c:
return 'Z';
case 0x2d:
return 'X';
case 0x2e:
return 'C';
case 0x2f:
return 'V';
case 0x30:
return 'B';
case 0x31:
return 'N';
case 0x32:
return 'M';
case 0x33:
return ',';
case 0x34:
return '.';
case 0x35:
return '/';
case 0x36:
is_in_shift = true;
break;
case 0x39:
return ' ';
case 0xaa:
is_in_shift = false;
break;
case 0xb6:
is_in_shift = false;
break;
}
return -1;
}
char get_last_key_pressed()
{
char scancode = inb(0x60);
if (is_in_shift) {
return keyboard_char(scancode);
}
return to_lower_char(keyboard_char(scancode));
}
void print_hex_digit(uint8_t digit)
{
digit = digit & 0xf;

View file

@ -13,25 +13,12 @@ static void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t s
return dstptr;
}
extern void jump_to_userspace();
void run_program(uint8_t* program, size_t length)
{
uint8_t* userland_code = (uint8_t*) 0x0;
uint8_t* userland_code = (uint8_t*) 0x00800000;
memcpy(userland_code, program, length);
print_hex_bytes(userland_code, 1);
terminal_putchar('\n');
asm ("\
mov $0x20 | 0x3, %%ax;\
movw %%ax, %%ds;\
movw %%ax, %%es;\
movw %%ax, %%fs;\
movw %%ax, %%gs;\
pushl $0x20 | 0x3; /* SS selector */ \
pushl $0x00c00100; /* ESP */ \
pushf; /* EFLAGS */ \
popl %%eax; orl $0x200, %%eax; pushl %%eax; /* Set interrupts in USERPACE */\
pushl $0x18 | 0x3; /* CS selector */\
pushl $0x0; /* EIP */ \
iret;":::"eax");
jump_to_userspace();
}

View file

@ -2,6 +2,7 @@
#include <kernel/idt.h>
#include <debugging.h>
#include <kernel/elf.h>
#include <kernel/pic.h>
/* Check if the compiler thinks you are targeting the wrong operating system. */
#if defined(__linux__)
@ -9,34 +10,45 @@
#endif
uint8_t program[] = {
0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x0 (Just a simple NOP-like instruction)
0xF4 // hlt (halts the CPU, should trap to kernel if interrupts enabled)
0xba, 0x09, 0x00, 0x80, 0x00, // mov $string, %edx
0xcd, 0x80, // int 0x80
0xeb, 0xfe, // jmp .
'H',
'e',
'l',
'l',
'o',
' ',
'W',
'o',
'r',
'l',
'd',
' ',
'f',
'r',
'o',
'm',
' ',
'r',
'i',
'n',
'g',
' ',
'3',
'!',
0x00,
};
void kernel_main(void)
{
/* Initialize terminal interface */
// terminal_initialize();
terminal_initialize();
init_pic();
idt_init();
// asm("int $13");
// asm("ljmp $0x18, $0x00c00100"); // Example: Far jump to user code segment with selector 0x18
print_hex_bytes(idt_init, 4);
terminal_putchar('\n');
run_program(program, 15);
/*
char buf[100];
// run_program(program, sizeof(program));
while (true) {
asm("mov %0, %%edx" :: "r" (buf));
asm("int $0x81");
terminal_writestring("newline");
terminal_putchar('\n');
}
*/
}
}

132
kernel/keyboard.c Normal file
View file

@ -0,0 +1,132 @@
#include <stdbool.h>
#include <stdint.h>
#include <strlib.h>
#include <kernel/tty.h>
static bool is_in_shift;
char buffer[100];
static size_t i;
static unsigned char keyboard_char(unsigned char scancode)
{
if (0x01 < scancode && scancode < 0x0B) {
return scancode - 2 + '1';
}
if (scancode == 0x0B) {
return '0';
}
switch (scancode) {
case 0x10:
return 'Q';
case 0x11:
return 'W';
case 0x12:
return 'E';
case 0x13:
return 'R';
case 0x14:
return 'T';
case 0x15:
return 'Y';
case 0x16:
return 'U';
case 0x17:
return 'I';
case 0x18:
return 'O';
case 0x19:
return 'P';
case 0x1a:
return '[';
case 0x1b:
return ']';
case 0x1c:
return '\n';
case 0x1d:
return '\b';
case 0x1e:
return 'A';
case 0x1f:
return 'S';
case 0x20:
return 'D';
case 0x21:
return 'F';
case 0x22:
return 'G';
case 0x23:
return 'H';
case 0x24:
return 'J';
case 0x25:
return 'K';
case 0x26:
return 'L';
case 0x27:
return ';';
case 0x28:
return '\'';
case 0x29:
return '`';
case 0x2a:
is_in_shift = true;
break;
case 0x2b:
return '\\';
case 0x2c:
return 'Z';
case 0x2d:
return 'X';
case 0x2e:
return 'C';
case 0x2f:
return 'V';
case 0x30:
return 'B';
case 0x31:
return 'N';
case 0x32:
return 'M';
case 0x33:
return ',';
case 0x34:
return '.';
case 0x35:
return '/';
case 0x36:
is_in_shift = true;
break;
case 0x39:
return ' ';
case 0xaa:
is_in_shift = false;
break;
case 0xb6:
is_in_shift = false;
break;
}
return -1;
}
void handle_keyboard(uint8_t scancode) {
char character;
if (is_in_shift) {
character = keyboard_char(scancode);
} else {
character = to_lower_char(keyboard_char(scancode));
}
if (character == -1) {
return;
}
buffer[i] = character;
i++;
terminal_putchar(character);
}