Added code to support getting interrupts from the PIC. Can now get some data from the keyboard, however, it's not quite working yet.

This commit is contained in:
2020-08-06 22:36:39 -05:00
parent db1a68188f
commit 49efafe173
15 changed files with 278 additions and 39 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
#ifndef KERNEL_VERSION_NUMBER #ifndef KERNEL_VERSION_NUMBER
#define KERNEL_VERSION_NUMBER "0.0.3-2" #define KERNEL_VERSION_NUMBER "0.0.3-46"
#endif #endif
+1 -1
View File
@@ -16,6 +16,6 @@ struct idt_ptr
} __attribute__((packed)); } __attribute__((packed));
void install_idt(void); void install_idt(void);
void idt_set_gate(struct idt_entry*, unsigned long, unsigned short, unsigned char); void idt_set_gate(unsigned char, unsigned long, unsigned short, unsigned char);
void load_idt(struct idt_ptr*); void load_idt(struct idt_ptr*);
#endif #endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef IRQ_H
#define IRQ_H
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef KB_H
#define KB_H
void handle_key_press(void);
void init_kb(void);
#endif
+1
View File
@@ -1,4 +1,5 @@
#ifndef KERNEL_H #ifndef KERNEL_H
#define KERNEL_H #define KERNEL_H
void kmain(); void kmain();
void kb_c();
#endif #endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef PIC_H
#define PIC_H
void pic_acknowledge(unsigned int);
void setup_pics(void);
#endif
+1
View File
@@ -4,4 +4,5 @@ void draw_string(char*, unsigned char, unsigned char);
int strlen(char*); int strlen(char*);
void clear_screen(void); void clear_screen(void);
void print_banner(void); void print_banner(void);
char* int_to_string(unsigned int, int);
#endif #endif
+34 -33
View File
@@ -18,44 +18,45 @@ void idt_install()
// For the kernel ring 8E is chosen // For the kernel ring 8E is chosen
// 100 for bits 7-5. 1 (present) 00 (the level in this case ring zero) // 100 for bits 7-5. 1 (present) 00 (the level in this case ring zero)
// 01110 for bits 4-0. This is always set to 14. // 01110 for bits 4-0. This is always set to 14.
idt_set_gate(&idt_entries[0], (unsigned int) isr0, 0x08, 0x8E); idt_set_gate(0, (unsigned int) isr0, 0x08, 0x8E);
idt_set_gate(&idt_entries[1], (unsigned int) isr1, 0x08, 0x8E); idt_set_gate(1, (unsigned int) isr1, 0x08, 0x8E);
idt_set_gate(&idt_entries[2], (unsigned int) isr2, 0x08, 0x8E); idt_set_gate(2, (unsigned int) isr2, 0x08, 0x8E);
idt_set_gate(&idt_entries[3], (unsigned int) isr3, 0x08, 0x8E); idt_set_gate(3, (unsigned int) isr3, 0x08, 0x8E);
idt_set_gate(&idt_entries[4], (unsigned int) isr4, 0x08, 0x8E); idt_set_gate(4, (unsigned int) isr4, 0x08, 0x8E);
idt_set_gate(&idt_entries[5], (unsigned int) isr5, 0x08, 0x8E); idt_set_gate(5, (unsigned int) isr5, 0x08, 0x8E);
idt_set_gate(&idt_entries[6], (unsigned int) isr6, 0x08, 0x8E); idt_set_gate(6, (unsigned int) isr6, 0x08, 0x8E);
idt_set_gate(&idt_entries[7], (unsigned int) isr7, 0x08, 0x8E); idt_set_gate(7, (unsigned int) isr7, 0x08, 0x8E);
idt_set_gate(&idt_entries[8], (unsigned int) isr8, 0x08, 0x8E); idt_set_gate(8, (unsigned int) isr8, 0x08, 0x8E);
idt_set_gate(&idt_entries[9], (unsigned int) isr9, 0x08, 0x8E); idt_set_gate(9, (unsigned int) isr9, 0x08, 0x8E);
idt_set_gate(&idt_entries[10], (unsigned int) isr10, 0x08, 0x8E); idt_set_gate(10, (unsigned int) isr10, 0x08, 0x8E);
idt_set_gate(&idt_entries[11], (unsigned int) isr11, 0x08, 0x8E); idt_set_gate(11, (unsigned int) isr11, 0x08, 0x8E);
idt_set_gate(&idt_entries[12], (unsigned int) isr12, 0x08, 0x8E); idt_set_gate(12, (unsigned int) isr12, 0x08, 0x8E);
idt_set_gate(&idt_entries[13], (unsigned int) isr13, 0x08, 0x8E); idt_set_gate(13, (unsigned int) isr13, 0x08, 0x8E);
idt_set_gate(&idt_entries[14], (unsigned int) isr14, 0x08, 0x8E); idt_set_gate(14, (unsigned int) isr14, 0x08, 0x8E);
idt_set_gate(&idt_entries[15], (unsigned int) isr15, 0x08, 0x8E); idt_set_gate(15, (unsigned int) isr15, 0x08, 0x8E);
idt_set_gate(&idt_entries[16], (unsigned int) isr16, 0x08, 0x8E); idt_set_gate(16, (unsigned int) isr16, 0x08, 0x8E);
idt_set_gate(&idt_entries[17], (unsigned int) isr17, 0x08, 0x8E); idt_set_gate(17, (unsigned int) isr17, 0x08, 0x8E);
idt_set_gate(&idt_entries[18], (unsigned int) isr18, 0x08, 0x8E); idt_set_gate(18, (unsigned int) isr18, 0x08, 0x8E);
idt_set_gate(&idt_entries[19], (unsigned int) isr19, 0x08, 0x8E); idt_set_gate(19, (unsigned int) isr19, 0x08, 0x8E);
idt_set_gate(&idt_entries[20], (unsigned int) isr20, 0x08, 0x8E); idt_set_gate(20, (unsigned int) isr20, 0x08, 0x8E);
idt_set_gate(&idt_entries[21], (unsigned int) isr21, 0x08, 0x8E); idt_set_gate(21, (unsigned int) isr21, 0x08, 0x8E);
idt_set_gate(&idt_entries[22], (unsigned int) isr22, 0x08, 0x8E); idt_set_gate(22, (unsigned int) isr22, 0x08, 0x8E);
idt_set_gate(&idt_entries[23], (unsigned int) isr23, 0x08, 0x8E); idt_set_gate(23, (unsigned int) isr23, 0x08, 0x8E);
idt_set_gate(&idt_entries[24], (unsigned int) isr24, 0x08, 0x8E); idt_set_gate(24, (unsigned int) isr24, 0x08, 0x8E);
idt_set_gate(&idt_entries[25], (unsigned int) isr25, 0x08, 0x8E); idt_set_gate(25, (unsigned int) isr25, 0x08, 0x8E);
idt_set_gate(&idt_entries[26], (unsigned int) isr26, 0x08, 0x8E); idt_set_gate(26, (unsigned int) isr26, 0x08, 0x8E);
idt_set_gate(&idt_entries[27], (unsigned int) isr27, 0x08, 0x8E); idt_set_gate(27, (unsigned int) isr27, 0x08, 0x8E);
idt_set_gate(&idt_entries[28], (unsigned int) isr28, 0x08, 0x8E); idt_set_gate(28, (unsigned int) isr28, 0x08, 0x8E);
idt_set_gate(&idt_entries[29], (unsigned int) isr29, 0x08, 0x8E); idt_set_gate(29, (unsigned int) isr29, 0x08, 0x8E);
idt_set_gate(&idt_entries[30], (unsigned int) isr30, 0x08, 0x8E); idt_set_gate(30, (unsigned int) isr30, 0x08, 0x8E);
idt_set_gate(&idt_entries[31], (unsigned int) isr31, 0x08, 0x8E); idt_set_gate(31, (unsigned int) isr31, 0x08, 0x8E);
load_idt(&idt); load_idt(&idt);
} }
void idt_set_gate(struct idt_entry* entry, unsigned long base, unsigned short sel, unsigned char flags) void idt_set_gate(unsigned char index, unsigned long base, unsigned short sel, unsigned char flags)
{ {
struct idt_entry* entry = &idt.idt_entries_start[index];
entry->base_lo = (base & 0xFFFF); entry->base_lo = (base & 0xFFFF);
entry->base_hi = (base >> 16) & 0xFFFF; entry->base_hi = (base >> 16) & 0xFFFF;
+2
View File
@@ -1,8 +1,10 @@
#include "../includes/interrupt_handler.h" #include "../includes/interrupt_handler.h"
#include "../includes/serial.h" #include "../includes/serial.h"
#include "../includes/screen.h"
void interrupt_handler(struct isr_state stack) void interrupt_handler(struct isr_state stack)
{ {
write_to_com(COM1_PORT, int_to_string(stack.int_no, 10));
write_to_com(COM1_PORT, "Divide by zero detected!\n"); write_to_com(COM1_PORT, "Divide by zero detected!\n");
write_to_com(COM1_PORT, "Halting system!\n"); write_to_com(COM1_PORT, "Halting system!\n");
asm("cli"); asm("cli");
+1 -1
View File
@@ -29,7 +29,7 @@ global isr27
global isr28 global isr28
global isr29 global isr29
global isr30 global isr30
global isr31 ; reserved global isr31 ; Reserved
isr0: ; division by zero isr0: ; division by zero
cli cli
+67
View File
@@ -0,0 +1,67 @@
global irq0 ; PIC Timer Interrupt
global irq1 ; Keyboard
global irq2 ; Cascade (Used internally by the two PICs; never raised)
global irq3 ; COM2
global irq4 ; COM1
global irq5 ; LPT2
global irq6 ; Floppy Disk
global irq7 ; LPT1
global irq8 ; CMOS realt-time clock
global irq9 ; Free for perpherals / legacy SCSI / NIC
global irq10 ; Free for perpherals / NIC
global irq11 ; Free for perpherals / NIC
global irq12 ; PS2 mouse
global irq13 ; FPU / Coprocessor / Inter-process
global irq14 ; Primary ATA HDD
global irq15 ; Secondary ATA HDD
extern handle_key_press
irq0:
iret
irq1:
call handle_key_press
iret
irq2:
iret
irq3:
iret
irq4:
iret
irq5:
iret
irq6:
iret
irq7:
iret
irq8:
iret
irq9:
iret
irq10:
iret
irq11:
iret
irq12:
iret
irq13:
iret
irq14:
iret
irq15:
iret
+27
View File
@@ -0,0 +1,27 @@
#include "../includes/kb.h"
#include "../includes/pic.h"
#include "../includes/screen.h"
#define KB_PORT 0x60
#define KB_STATUS_PORT 0x64
void handle_key_press()
{
pic_acknowledge(33);
unsigned char status = inb(KB_STATUS_PORT);
if(status & 0x01)
{
char keycode = inb(KB_PORT);
if(keycode < 0) return;
draw_string(int_to_string(keycode, 10), 0xF, 0x0);
}
}
void init_kb()
{
outb(0x21, 0xFD);
}
+15 -3
View File
@@ -4,6 +4,8 @@
#include "../includes/serial.h" #include "../includes/serial.h"
#include "../includes/screen.h" #include "../includes/screen.h"
#include "../includes/loader.h" #include "../includes/loader.h"
#include "../includes/pic.h"
#include "../includes/kb.h"
struct multiboot_header header __attribute((section(".multiboot"))) = (struct multiboot_header) {.magic = 0x1BADB002, .flags = 0x1, .checksum = -464367619}; struct multiboot_header header __attribute((section(".multiboot"))) = (struct multiboot_header) {.magic = 0x1BADB002, .flags = 0x1, .checksum = -464367619};
@@ -26,9 +28,14 @@ void kmain()
print_message("Installing IDT...\n", 0xF, 0x0); print_message("Installing IDT...\n", 0xF, 0x0);
idt_install(); idt_install();
print_message("IDT installed.\n", 0xF, 0x0); print_message("IDT installed.\n", 0xF, 0x0);
//asm("xchg %bx, %bx"); // Boch's break point
int i = 5 / 0; setup_pics();
asm("hlt"); //kb
init_kb();
//asm("xchg %bx, %bx");
asm("sti");
//for(;;);
idle();
} }
void print_message(unsigned char* msg, unsigned char fg, unsigned char bg) void print_message(unsigned char* msg, unsigned char fg, unsigned char bg)
@@ -36,3 +43,8 @@ void print_message(unsigned char* msg, unsigned char fg, unsigned char bg)
write_to_com(COM1_PORT, msg); write_to_com(COM1_PORT, msg);
draw_string(msg, fg, bg); draw_string(msg, fg, bg);
} }
void idle()
{
for(;;) asm("hlt");
}
+58
View File
@@ -0,0 +1,58 @@
#include "../includes/pic.h"
#include "../includes/io.h"
#include "../includes/idt.h"
#include "../includes/irq.h"
#define PIC1_PORT 0x20
#define PIC1_DATA_PORT 0X21
#define PIC2_PORT 0xA0
#define PIC2_DATA_PORT 0XA1
#define PIC1_START_INTERRUPT 0x20
#define PIC2_START_INTERRUPT 0x28
#define PIC2_END_INTERRUPT PIC2_START_INTERRUPT + 7
#define PIC_ACK 0x20
void pic_acknowledge(unsigned int interrupt_no)
{
if (interrupt_no < PIC2_START_INTERRUPT)
outb(PIC1_PORT, PIC_ACK);
else
outb(PIC2_PORT, PIC_ACK);
}
void setup_pics(void)
{
// The PIC uses Initialization Command Words (ICW) to communicate.
// So we start with the first ICW, 0x11, this tells the PIC to expect
// 3 more ICWs.
outb(PIC1_PORT, 0x11);
outb(PIC2_PORT, 0x11);
// This tells the pic what offset to use when it generates the interrupt numbers.
// Since the first 32 ISRs are reserved by the CPU we must start at IRS32 and work
// our way up. When the PIC recieves an interrupt on it's input line, it will add
// the supplied values to that number before sending the newly made number to the CPU.
// Thereby remapping an interrupt number that would have normally conflicted with the
// values in the IDT.
outb(PIC1_DATA_PORT, PIC1_START_INTERRUPT);
outb(PIC2_DATA_PORT, PIC2_START_INTERRUPT);
// This ICW allows for cascading of their outputs to inputs between each other.
// I'm not sure what that really means but at this current time I'm not going to
// be doing this, so the bits will all be set to zero.
outb(PIC1_DATA_PORT, 0x00);
outb(PIC2_DATA_PORT, 0x00);
// This is the environment info, and setting the lowest bit tells the PICs
// that we're running in 80x86 mode.
outb(PIC1_DATA_PORT, 0x01);
outb(PIC2_DATA_PORT, 0x01);
// Finally, we have the interrupt masks.
outb(PIC1_DATA_PORT, 0xFF);
outb(PIC2_DATA_PORT, 0xFF);
idt_set_gate(33, (unsigned long) &irq1, 0x08, 0x8E);
}
+35
View File
@@ -119,3 +119,38 @@ int strlen(char* string)
return len; return len;
} }
//Code reference:
//http://www.strudel.org.uk/itoa/
char* int_to_string(unsigned int value, int base)
{
static char buf[32] = {0};
//void* ptr = Malloc(32);
//if(ptr == 0)
//{
//puts("Malloc failed to allocate!\n");
//return "";
//}
//char buf = (char*) ptr;
if(value == 0)
{
buf[0] = '0';
//*buf++ = '0';
//return buf;
return &buf[0];
}
int i = 30;
for(; value && i; --i, value /= base)
{
//*buf++ = "0123456789ABCDEF"[value % base];
buf[i] = "0123456789ABCDEF"[value % base];
}
//Free(ptr);
//return buf;
return &buf[i+1];
}