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:
+1
-1
@@ -1,3 +1,3 @@
|
||||
#ifndef KERNEL_VERSION_NUMBER
|
||||
#define KERNEL_VERSION_NUMBER "0.0.3-2"
|
||||
#define KERNEL_VERSION_NUMBER "0.0.3-46"
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -16,6 +16,6 @@ struct idt_ptr
|
||||
} __attribute__((packed));
|
||||
|
||||
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*);
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef KB_H
|
||||
#define KB_H
|
||||
|
||||
void handle_key_press(void);
|
||||
void init_kb(void);
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
#ifndef KERNEL_H
|
||||
#define KERNEL_H
|
||||
void kmain();
|
||||
void kb_c();
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef PIC_H
|
||||
#define PIC_H
|
||||
|
||||
void pic_acknowledge(unsigned int);
|
||||
void setup_pics(void);
|
||||
|
||||
#endif
|
||||
@@ -4,4 +4,5 @@ void draw_string(char*, unsigned char, unsigned char);
|
||||
int strlen(char*);
|
||||
void clear_screen(void);
|
||||
void print_banner(void);
|
||||
char* int_to_string(unsigned int, int);
|
||||
#endif
|
||||
|
||||
+34
-33
@@ -18,44 +18,45 @@ void idt_install()
|
||||
// For the kernel ring 8E is chosen
|
||||
// 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.
|
||||
idt_set_gate(&idt_entries[0], (unsigned int) isr0, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[1], (unsigned int) isr1, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[2], (unsigned int) isr2, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[3], (unsigned int) isr3, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[4], (unsigned int) isr4, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[5], (unsigned int) isr5, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[6], (unsigned int) isr6, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[7], (unsigned int) isr7, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[8], (unsigned int) isr8, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[9], (unsigned int) isr9, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[10], (unsigned int) isr10, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[11], (unsigned int) isr11, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[12], (unsigned int) isr12, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[13], (unsigned int) isr13, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[14], (unsigned int) isr14, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[15], (unsigned int) isr15, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[16], (unsigned int) isr16, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[17], (unsigned int) isr17, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[18], (unsigned int) isr18, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[19], (unsigned int) isr19, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[20], (unsigned int) isr20, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[21], (unsigned int) isr21, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[22], (unsigned int) isr22, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[23], (unsigned int) isr23, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[24], (unsigned int) isr24, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[25], (unsigned int) isr25, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[26], (unsigned int) isr26, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[27], (unsigned int) isr27, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[28], (unsigned int) isr28, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[29], (unsigned int) isr29, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[30], (unsigned int) isr30, 0x08, 0x8E);
|
||||
idt_set_gate(&idt_entries[31], (unsigned int) isr31, 0x08, 0x8E);
|
||||
idt_set_gate(0, (unsigned int) isr0, 0x08, 0x8E);
|
||||
idt_set_gate(1, (unsigned int) isr1, 0x08, 0x8E);
|
||||
idt_set_gate(2, (unsigned int) isr2, 0x08, 0x8E);
|
||||
idt_set_gate(3, (unsigned int) isr3, 0x08, 0x8E);
|
||||
idt_set_gate(4, (unsigned int) isr4, 0x08, 0x8E);
|
||||
idt_set_gate(5, (unsigned int) isr5, 0x08, 0x8E);
|
||||
idt_set_gate(6, (unsigned int) isr6, 0x08, 0x8E);
|
||||
idt_set_gate(7, (unsigned int) isr7, 0x08, 0x8E);
|
||||
idt_set_gate(8, (unsigned int) isr8, 0x08, 0x8E);
|
||||
idt_set_gate(9, (unsigned int) isr9, 0x08, 0x8E);
|
||||
idt_set_gate(10, (unsigned int) isr10, 0x08, 0x8E);
|
||||
idt_set_gate(11, (unsigned int) isr11, 0x08, 0x8E);
|
||||
idt_set_gate(12, (unsigned int) isr12, 0x08, 0x8E);
|
||||
idt_set_gate(13, (unsigned int) isr13, 0x08, 0x8E);
|
||||
idt_set_gate(14, (unsigned int) isr14, 0x08, 0x8E);
|
||||
idt_set_gate(15, (unsigned int) isr15, 0x08, 0x8E);
|
||||
idt_set_gate(16, (unsigned int) isr16, 0x08, 0x8E);
|
||||
idt_set_gate(17, (unsigned int) isr17, 0x08, 0x8E);
|
||||
idt_set_gate(18, (unsigned int) isr18, 0x08, 0x8E);
|
||||
idt_set_gate(19, (unsigned int) isr19, 0x08, 0x8E);
|
||||
idt_set_gate(20, (unsigned int) isr20, 0x08, 0x8E);
|
||||
idt_set_gate(21, (unsigned int) isr21, 0x08, 0x8E);
|
||||
idt_set_gate(22, (unsigned int) isr22, 0x08, 0x8E);
|
||||
idt_set_gate(23, (unsigned int) isr23, 0x08, 0x8E);
|
||||
idt_set_gate(24, (unsigned int) isr24, 0x08, 0x8E);
|
||||
idt_set_gate(25, (unsigned int) isr25, 0x08, 0x8E);
|
||||
idt_set_gate(26, (unsigned int) isr26, 0x08, 0x8E);
|
||||
idt_set_gate(27, (unsigned int) isr27, 0x08, 0x8E);
|
||||
idt_set_gate(28, (unsigned int) isr28, 0x08, 0x8E);
|
||||
idt_set_gate(29, (unsigned int) isr29, 0x08, 0x8E);
|
||||
idt_set_gate(30, (unsigned int) isr30, 0x08, 0x8E);
|
||||
idt_set_gate(31, (unsigned int) isr31, 0x08, 0x8E);
|
||||
|
||||
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_hi = (base >> 16) & 0xFFFF;
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "../includes/interrupt_handler.h"
|
||||
#include "../includes/serial.h"
|
||||
#include "../includes/screen.h"
|
||||
|
||||
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, "Halting system!\n");
|
||||
asm("cli");
|
||||
|
||||
@@ -29,7 +29,7 @@ global isr27
|
||||
global isr28
|
||||
global isr29
|
||||
global isr30
|
||||
global isr31 ; reserved
|
||||
global isr31 ; Reserved
|
||||
|
||||
isr0: ; division by zero
|
||||
cli
|
||||
|
||||
@@ -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
@@ -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
@@ -4,6 +4,8 @@
|
||||
#include "../includes/serial.h"
|
||||
#include "../includes/screen.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};
|
||||
|
||||
@@ -26,9 +28,14 @@ void kmain()
|
||||
print_message("Installing IDT...\n", 0xF, 0x0);
|
||||
idt_install();
|
||||
print_message("IDT installed.\n", 0xF, 0x0);
|
||||
|
||||
int i = 5 / 0;
|
||||
asm("hlt");
|
||||
//asm("xchg %bx, %bx"); // Boch's break point
|
||||
setup_pics();
|
||||
//kb
|
||||
init_kb();
|
||||
//asm("xchg %bx, %bx");
|
||||
asm("sti");
|
||||
//for(;;);
|
||||
idle();
|
||||
}
|
||||
|
||||
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);
|
||||
draw_string(msg, fg, bg);
|
||||
}
|
||||
|
||||
void idle()
|
||||
{
|
||||
for(;;) asm("hlt");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -119,3 +119,38 @@ int strlen(char* string)
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user