Moving components modules to a more proper directory
This commit is contained in:
48
components/framebuffer/framebuffer.c
Normal file
48
components/framebuffer/framebuffer.c
Normal file
@@ -0,0 +1,48 @@
|
||||
// Driver implementation for Jank's text frame buffer
|
||||
|
||||
// Buffer can display 80 columns by 25 Rows
|
||||
// Start of buffer is at (real)address 0x000B8000
|
||||
// Memory at this section is divided into 16-bit cells
|
||||
// | 15-8 | 7-4 | 0-3
|
||||
// | Asci | FG | BG
|
||||
#include "types.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
// State trackers from header
|
||||
static u8* Frame_Buffer = (u8*)FRAME_BUFFER_ADDR;
|
||||
s32 Frame_Buffer_Cursor = 0x0000;
|
||||
|
||||
void frame_buffer_newline() {
|
||||
while(Frame_Buffer_Cursor != (AREA*8)) {
|
||||
if((Frame_Buffer_Cursor % 160) == 0) {
|
||||
break;
|
||||
Frame_Buffer_Cursor+=160;
|
||||
}
|
||||
else {
|
||||
Frame_Buffer_Cursor+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Writes character to a given cell in the framebuffer
|
||||
// @cell parameter is the logical (linear)index into the buffer
|
||||
void write_cell_fb(u8 c, u8 fg, u8 bg) {
|
||||
Frame_Buffer[Frame_Buffer_Cursor] = c;
|
||||
Frame_Buffer[Frame_Buffer_Cursor+1] = (fg & 0x0f << 4) | (bg & 0x0f);
|
||||
Frame_Buffer_Cursor += 2;
|
||||
}
|
||||
|
||||
void clear_fb(void) {
|
||||
for(unsigned cell=0;cell<AREA; cell+=2) {
|
||||
write_cell_fb(' ', 0x00, 0x00);
|
||||
}
|
||||
Frame_Buffer_Cursor = 0x0000;
|
||||
}
|
||||
|
||||
// Takes the linear indexed position to move the cursos, if there is nothing at that position we should still have something there
|
||||
void fb_move_cursor(u16 position) {
|
||||
serialport_write_byte(FB_CMD, FB_HIGH_CMD);
|
||||
serialport_write_byte(FB_DATA, ((position >> 8) & 0x00ff) );
|
||||
serialport_write_byte(FB_CMD, FB_LOW_CMD);
|
||||
serialport_write_byte(FB_DATA, position & 0x00ff);
|
||||
}
|
||||
|
||||
52
components/framebuffer/framebuffer.h
Normal file
52
components/framebuffer/framebuffer.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "types.h"
|
||||
#include "serial.h"
|
||||
#include "ports.h"
|
||||
#ifndef FRAMEBUFFER_H
|
||||
#define FRAMEBUFFER_H
|
||||
|
||||
#define COLUMNS 80
|
||||
#define ROWS 25
|
||||
#define AREA ( COLUMNS * ROWS )
|
||||
|
||||
// frame buffer port commansd
|
||||
#define FB_CMD 0x3d4
|
||||
#define FB_DATA 0x3d5
|
||||
|
||||
#define FB_HIGH_CMD 14
|
||||
#define FB_LOW_CMD 15
|
||||
|
||||
// address of our frame buffer
|
||||
#define FRAME_BUFFER_ADDR 0x000B8000
|
||||
|
||||
// Logical index of a cell in the frame buffer
|
||||
#define FRAME_CELL(cell_) (cell_ * 2)
|
||||
|
||||
// Colors available in text framebuffer
|
||||
#define Black 0x01
|
||||
#define Blue 0x02
|
||||
#define Green 0x03
|
||||
#define Cyan 0x04
|
||||
#define Red 0x05
|
||||
#define Magenta 0x05
|
||||
#define Brown 0x06
|
||||
#define LightGrey 0x07
|
||||
#define DarkGrey 0x08
|
||||
#define LightBlue 0x09
|
||||
#define LightGreen 0x0a
|
||||
#define LightCyan 0x0b
|
||||
#define LightRed 0x0c
|
||||
#define LightMagenta 0x0d
|
||||
#define LightBrown 0x0e
|
||||
#define White 0x0f
|
||||
|
||||
extern s32 Frame_Buffer_Cursor;
|
||||
|
||||
void frame_buffer_newline();
|
||||
|
||||
void write_cell_fb(u8, u8, u8);
|
||||
|
||||
void clear_fb(void);
|
||||
|
||||
void fb_move_cursor(u16);
|
||||
|
||||
#endif
|
||||
43
components/gdt/gdt.c
Normal file
43
components/gdt/gdt.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "gdt.h"
|
||||
// Congirures a given gdt entry base on the entry index given
|
||||
void gdt_configure_entry(u32 entry, u32 base, u32 limit, u8 access, u8 gran) {
|
||||
// base address
|
||||
gdt_entries[entry].low_base = (base & 0xffff);
|
||||
gdt_entries[entry].middle_base = (base >> 16) & 0xff;
|
||||
gdt_entries[entry].high_base = (base >> 24) & 0xff;
|
||||
|
||||
// descriptor limits
|
||||
gdt_entries[entry].low_limit = (limit & 0xffff);
|
||||
gdt_entries[entry].granular = ((limit >> 16) & 0x0f);
|
||||
|
||||
gdt_entries[entry].granular |= (gran & 0xf0);
|
||||
gdt_entries[entry].access = access;
|
||||
}
|
||||
|
||||
// Configure the gdt pointer desribed in gdt.h as type GDT_PTR
|
||||
void gdt_configure() {
|
||||
// gdt_ptr configuration
|
||||
gdt_ptr.size = (sizeof(struct GDT_Entry) * NO_GDT_ENTRIES) - 1;
|
||||
|
||||
// First entry is just the null descriptor and is left along overall
|
||||
gdt_configure_entry(0, 0, 0, 0, 0);
|
||||
|
||||
// Second entry: code segment base adders
|
||||
// Base address: 0
|
||||
// limit: 4GB
|
||||
// Granularity: 4KB
|
||||
// 32-bit opcodes
|
||||
// Code segment selector
|
||||
gdt_configure_entry(1, 0, 0xffffffff, 0x9a, 0xcf); // code segment
|
||||
|
||||
// Finally the data segment
|
||||
// All the same except the desriptor type specifies that its data
|
||||
gdt_configure_entry(2, 0, 0xffffffff, 0x92, 0xcf); // data segment
|
||||
|
||||
// user mode segments
|
||||
gdt_configure_entry(3, 0, 0xffffffff, 0xfa, 0xcf);
|
||||
gdt_configure_entry(4, 0, 0xffffffff, 0xf2, 0xcf);
|
||||
|
||||
// Load in the new changes to the gdt
|
||||
load_gdt();
|
||||
}
|
||||
32
components/gdt/gdt.h
Normal file
32
components/gdt/gdt.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef GDT_H
|
||||
#define GDT_H
|
||||
#include "types.h"
|
||||
|
||||
#define NO_GDT_ENTRIES 5
|
||||
|
||||
struct GDT_Entry {
|
||||
u16 low_limit;
|
||||
u16 low_base;
|
||||
u8 middle_base;
|
||||
u8 access;
|
||||
u8 granular;
|
||||
u8 high_base;
|
||||
}__attribute__((packed));
|
||||
|
||||
// Contains the pointer to the first gdt entry as well as the size(of the whole table(?))
|
||||
struct GDT_PTR {
|
||||
u16 size;
|
||||
u32 address;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct GDT_Entry gdt_entries[NO_GDT_ENTRIES];
|
||||
struct GDT_PTR gdt_ptr;
|
||||
|
||||
// this func is actually taken care of in gdt_seg.s
|
||||
extern void load_gdt();
|
||||
|
||||
void gdt_configure_entry(u32 entry, u32 base, u32 limit, u8 access, u8 gran);
|
||||
|
||||
void gdt_configure();
|
||||
|
||||
#endif
|
||||
17
components/gdt/gdt_seg.s
Normal file
17
components/gdt/gdt_seg.s
Normal file
@@ -0,0 +1,17 @@
|
||||
global load_gdt
|
||||
extern gdt_ptr
|
||||
|
||||
load_gdt:
|
||||
mov ax, 0x10 ; offset in the gdt to our data segment
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
jmp 0x08:flush_cs ; far jump to the code segment
|
||||
|
||||
flush_cs:
|
||||
lgdt [gdt_ptr]
|
||||
ret
|
||||
|
||||
|
||||
170
components/interrupts/interrupt_entry.s
Normal file
170
components/interrupts/interrupt_entry.s
Normal file
@@ -0,0 +1,170 @@
|
||||
; Dispatching to our interrupt handler code from assembly because some of this is
|
||||
; enourmous pain in C
|
||||
|
||||
; Save the register state
|
||||
; call the C handler
|
||||
; executes iret(expects the stack to look like struct stack_state)
|
||||
|
||||
|
||||
; If the interrupt we need to handle doesn't produce an error code then must provide a 0
|
||||
; for consistency
|
||||
|
||||
extern interrupt_handler
|
||||
extern cpu_reg_state
|
||||
extern stack_state
|
||||
extern idt_ptr
|
||||
extern irq_handler
|
||||
|
||||
global load_idt
|
||||
load_idt:
|
||||
lidt [idt_ptr]
|
||||
ret
|
||||
|
||||
%macro irq 2
|
||||
global irq_handler_%1
|
||||
irq_handler_%1:
|
||||
push dword 0
|
||||
push dword %2
|
||||
jmp common_irq_handler
|
||||
%endmacro
|
||||
|
||||
%macro no_err_handler 1
|
||||
global no_err_handler_%1 ; defined in interrupts.h
|
||||
no_err_handler_%1:
|
||||
push dword 0
|
||||
push dword %1
|
||||
jmp common_int_handler
|
||||
%endmacro
|
||||
|
||||
; deals with the intterrupts that do give us an error code
|
||||
%macro err_code_handler 1
|
||||
global err_code_handler_%1
|
||||
err_code_handler_%1:
|
||||
push dword %1
|
||||
jmp common_int_handler
|
||||
%endmacro
|
||||
|
||||
extern interrupt_handler ; external handler (interrupts.c)
|
||||
common_int_handler:
|
||||
; save thigns before do our C-call
|
||||
pushad
|
||||
;push eax ecx edx ebx
|
||||
;push esp ebp esi edi
|
||||
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
; load the kernel segment descriptor
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov eax, esp ; pushing the stack into the next call
|
||||
push eax
|
||||
mov eax, interrupt_handler
|
||||
call eax ; preserve the eip register past this call
|
||||
|
||||
; segments
|
||||
pop eax
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
|
||||
popad
|
||||
|
||||
add esp, 8
|
||||
; special instruction which lets us jump back to code
|
||||
; which was previously interrupted
|
||||
iret
|
||||
|
||||
|
||||
no_err_handler 0
|
||||
no_err_handler 1
|
||||
no_err_handler 2
|
||||
no_err_handler 3
|
||||
no_err_handler 4
|
||||
no_err_handler 5
|
||||
no_err_handler 6
|
||||
no_err_handler 7
|
||||
|
||||
err_code_handler 8
|
||||
|
||||
no_err_handler 9
|
||||
|
||||
err_code_handler 10
|
||||
err_code_handler 11
|
||||
err_code_handler 12
|
||||
err_code_handler 13
|
||||
err_code_handler 14
|
||||
|
||||
no_err_handler 15
|
||||
no_err_handler 16
|
||||
no_err_handler 17
|
||||
no_err_handler 18
|
||||
no_err_handler 19
|
||||
no_err_handler 20
|
||||
no_err_handler 21
|
||||
no_err_handler 22
|
||||
no_err_handler 23
|
||||
no_err_handler 24
|
||||
no_err_handler 25
|
||||
no_err_handler 26
|
||||
no_err_handler 27
|
||||
no_err_handler 28
|
||||
no_err_handler 29
|
||||
no_err_handler 30
|
||||
no_err_handler 31
|
||||
|
||||
|
||||
common_irq_handler:
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
mov eax, esp
|
||||
push eax
|
||||
mov eax, irq_handler
|
||||
call eax
|
||||
pop eax
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
|
||||
popa
|
||||
add esp, 8
|
||||
iret
|
||||
|
||||
|
||||
; Remapped IRQ's for the APIC
|
||||
|
||||
; starting from irq 0 -> 15 but remapped to 32 -> 47
|
||||
irq 0, 32
|
||||
irq 1, 33
|
||||
irq 2, 34
|
||||
irq 3, 35
|
||||
irq 4, 36
|
||||
irq 5, 37
|
||||
irq 6, 38
|
||||
irq 7, 39
|
||||
irq 8, 40
|
||||
irq 9, 41
|
||||
irq 10, 42
|
||||
irq 11, 43
|
||||
irq 12, 44
|
||||
irq 13, 45
|
||||
irq 14, 46
|
||||
irq 15, 47
|
||||
217
components/interrupts/interrupts.c
Normal file
217
components/interrupts/interrupts.c
Normal file
@@ -0,0 +1,217 @@
|
||||
#include "stlio.h"
|
||||
#include "interrupts.h"
|
||||
#include "serial.h"
|
||||
#include "mem.h"
|
||||
#include "types.h"
|
||||
#include "ports.h"
|
||||
#include "pit.h"
|
||||
#include "kbd.h"
|
||||
|
||||
const char* err_msg[] = {
|
||||
"Divide by zero\n",
|
||||
"Debug Exception\n",
|
||||
"Non Maskable Interrupt Exception\n",
|
||||
"Breakpoint Exception\n",
|
||||
"Into Detected Overflow Exception\n",
|
||||
"Out of Bounds Exception\n",
|
||||
"Invalid Opcode Exception\n",
|
||||
"No Coprocessor Exception\n",
|
||||
"Double Fault Exception\n",
|
||||
"Coprocessor Segment Overrun Exception\n",
|
||||
"Bad TSS Exception\n",
|
||||
"Segment Not Present Exception\n",
|
||||
"Stack Fault Exception\n",
|
||||
"General Protection Fault Exception\n",
|
||||
"Page Fault Exception\n",
|
||||
"Unknown Interrupt Exception\n",
|
||||
"Coprocessor Fault Exception\n",
|
||||
"Alignment Check Exception (486+)\n",
|
||||
"Machine Check Exception (Pentium/586+)\n",
|
||||
"Reserved Exceptions\n", /* for 19 - 31 */
|
||||
};
|
||||
|
||||
extern void load_idt(); // found in interrupts_entry.s
|
||||
extern void no_err_handler_0();
|
||||
extern void no_err_handler_1();
|
||||
extern void no_err_handler_2();
|
||||
extern void no_err_handler_3();
|
||||
extern void no_err_handler_4();
|
||||
extern void no_err_handler_5();
|
||||
extern void no_err_handler_6();
|
||||
extern void no_err_handler_7();
|
||||
|
||||
extern void err_code_handler_8();
|
||||
|
||||
extern void no_err_handler_9();
|
||||
|
||||
extern void err_code_handler_10();
|
||||
extern void err_code_handler_11();
|
||||
extern void err_code_handler_12();
|
||||
extern void err_code_handler_13();
|
||||
extern void err_code_handler_14();
|
||||
|
||||
extern void no_err_handler_15();
|
||||
extern void no_err_handler_16();
|
||||
extern void no_err_handler_17();
|
||||
extern void no_err_handler_18();
|
||||
extern void no_err_handler_19();
|
||||
extern void no_err_handler_20();
|
||||
extern void no_err_handler_21();
|
||||
extern void no_err_handler_22();
|
||||
extern void no_err_handler_23();
|
||||
extern void no_err_handler_24();
|
||||
extern void no_err_handler_25();
|
||||
extern void no_err_handler_26();
|
||||
extern void no_err_handler_27();
|
||||
extern void no_err_handler_28();
|
||||
extern void no_err_handler_29();
|
||||
extern void no_err_handler_30();
|
||||
extern void no_err_handler_31();
|
||||
|
||||
// Remapped IRQ's
|
||||
extern void irq_handler_0();
|
||||
extern void irq_handler_1();
|
||||
extern void irq_handler_2();
|
||||
extern void irq_handler_3();
|
||||
extern void irq_handler_4();
|
||||
extern void irq_handler_5();
|
||||
extern void irq_handler_6();
|
||||
extern void irq_handler_7();
|
||||
extern void irq_handler_8();
|
||||
extern void irq_handler_9();
|
||||
extern void irq_handler_10();
|
||||
extern void irq_handler_11();
|
||||
extern void irq_handler_12();
|
||||
extern void irq_handler_13();
|
||||
extern void irq_handler_14();
|
||||
extern void irq_handler_15();
|
||||
|
||||
void* irq_handlers[16] = {0};
|
||||
|
||||
void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs) {
|
||||
// Configuring a single given entry in the IDT table
|
||||
IDT[t_idx].offset_low = (base & 0xffff);
|
||||
IDT[t_idx].offset_high = ((base >> 16) & 0xffff);
|
||||
|
||||
IDT[t_idx].type_attrs = type_attrs;
|
||||
IDT[t_idx].zero = 0;
|
||||
IDT[t_idx].selector = sel;
|
||||
}
|
||||
|
||||
// Generic interrupt handler to be used later on
|
||||
void interrupt_handler(struct cpu_reg_state* cpu) {
|
||||
// treating things on the stack like it were a cpu_reg_state
|
||||
// NOTE: dummy stuff to stop gcc from complaining atm
|
||||
printf("handled exception\n");
|
||||
if(cpu->int_no < 32) {
|
||||
printf(err_msg[cpu->int_no]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the index into the table and the handler(strut* cpu_reg_state)
|
||||
void init_irq_handler(u32 irq, void (*handler)(struct cpu_reg_state* cpu)) {
|
||||
// install handle
|
||||
irq_handlers[irq] = handler;
|
||||
}
|
||||
|
||||
void irq_handler(struct cpu_reg_state* cpu) {
|
||||
void (*handler)(struct cpu_reg_state* cpu);
|
||||
// Dispatcher for irq's
|
||||
handler = irq_handlers[cpu->int_no - 0x20];
|
||||
// Handler the timer by hand because fuck this tbh
|
||||
if(handler) {
|
||||
handler(cpu);
|
||||
}
|
||||
// pretend like nothing happend for now
|
||||
if(cpu->int_no >= 40) {
|
||||
serialport_write_byte(0xa0, 0x20);
|
||||
}
|
||||
// notify master pic controller that we're done handling the interrupt
|
||||
serialport_write_byte(0x20, 0x20);
|
||||
}
|
||||
|
||||
void init_idt() {
|
||||
// setup special idt pointer
|
||||
idt_ptr.address = (u32)(&IDT);
|
||||
idt_ptr.limit = (sizeof(struct IDT_Entry) * IDT_SIZE) - 1;
|
||||
// clear table
|
||||
memset((u8*)IDT, 0x00, (sizeof(struct IDT_Entry) * IDT_SIZE));
|
||||
// add interrupt service routines here
|
||||
setup_idt_entry(0,(u32)no_err_handler_0,0x08, 0x8e);
|
||||
setup_idt_entry(1,(u32)no_err_handler_1,0x08, 0x8e);
|
||||
setup_idt_entry(2,(u32)no_err_handler_2,0x08, 0x8e);
|
||||
setup_idt_entry(3,(u32)no_err_handler_3,0x08, 0x8e);
|
||||
setup_idt_entry(4,(u32)no_err_handler_4,0x08, 0x8e);
|
||||
setup_idt_entry(5,(u32)no_err_handler_5,0x08, 0x8e);
|
||||
setup_idt_entry(6,(u32)no_err_handler_6,0x08, 0x8e);
|
||||
setup_idt_entry(7,(u32)no_err_handler_7,0x08, 0x8e);
|
||||
|
||||
setup_idt_entry(8,(u32)err_code_handler_8,0x08, 0x8e);
|
||||
|
||||
setup_idt_entry(9,(u32)no_err_handler_9,0x08, 0x8e);
|
||||
|
||||
|
||||
setup_idt_entry(10,(u32)err_code_handler_10,0x08, 0x8e);
|
||||
setup_idt_entry(11,(u32)err_code_handler_11,0x08, 0x8e);
|
||||
setup_idt_entry(12,(u32)err_code_handler_12,0x08, 0x8e);
|
||||
setup_idt_entry(13,(u32)err_code_handler_13,0x08, 0x8e);
|
||||
setup_idt_entry(14,(u32)err_code_handler_14,0x08, 0x8e);
|
||||
|
||||
setup_idt_entry(15,(u32)no_err_handler_15,0x08, 0x8e);
|
||||
setup_idt_entry(16,(u32)no_err_handler_16,0x08, 0x8e);
|
||||
setup_idt_entry(17,(u32)no_err_handler_17,0x08, 0x8e);
|
||||
setup_idt_entry(18,(u32)no_err_handler_18,0x08, 0x8e);
|
||||
setup_idt_entry(19,(u32)no_err_handler_19,0x08, 0x8e);
|
||||
setup_idt_entry(20,(u32)no_err_handler_20,0x08, 0x8e);
|
||||
setup_idt_entry(21,(u32)no_err_handler_21,0x08, 0x8e);
|
||||
setup_idt_entry(22,(u32)no_err_handler_22,0x08, 0x8e);
|
||||
setup_idt_entry(23,(u32)no_err_handler_23,0x08, 0x8e);
|
||||
setup_idt_entry(24,(u32)no_err_handler_24,0x08, 0x8e);
|
||||
setup_idt_entry(25,(u32)no_err_handler_25,0x08, 0x8e);
|
||||
setup_idt_entry(26,(u32)no_err_handler_26,0x08, 0x8e);
|
||||
setup_idt_entry(27,(u32)no_err_handler_27,0x08, 0x8e);
|
||||
setup_idt_entry(28,(u32)no_err_handler_28,0x08, 0x8e);
|
||||
setup_idt_entry(29,(u32)no_err_handler_29,0x08, 0x8e);
|
||||
setup_idt_entry(30,(u32)no_err_handler_30,0x08, 0x8e);
|
||||
setup_idt_entry(31,(u32)no_err_handler_31,0x08, 0x8e);
|
||||
|
||||
// Load IDT with all the new information in place, ready to use
|
||||
load_idt();
|
||||
|
||||
// clear table in case there's garbage in there
|
||||
memset((u8*)irq_handlers, 0, sizeof(void*));
|
||||
irq_handlers[0] = pit_inc_ticks; // LULW
|
||||
|
||||
// Remap irq's to proper location
|
||||
serialport_write_byte(0x20, 0x11);
|
||||
serialport_write_byte(0xA0, 0x11);
|
||||
serialport_write_byte(0x21, 0x20);
|
||||
serialport_write_byte(0xA1, 0x28);
|
||||
serialport_write_byte(0x21, 0x04);
|
||||
serialport_write_byte(0xA1, 0x02);
|
||||
serialport_write_byte(0x21, 0x01);
|
||||
serialport_write_byte(0xA1, 0x01);
|
||||
serialport_write_byte(0x21, 0x0);
|
||||
serialport_write_byte(0xA1, 0x0);
|
||||
|
||||
// Install handlers for irq's
|
||||
setup_idt_entry(32,(u32)irq_handler_0,0x08, 0x8e);
|
||||
setup_idt_entry(33,(u32)irq_handler_1,0x08, 0x8e);
|
||||
setup_idt_entry(34,(u32)irq_handler_2,0x08, 0x8e);
|
||||
setup_idt_entry(35,(u32)irq_handler_3,0x08, 0x8e);
|
||||
setup_idt_entry(36,(u32)irq_handler_4,0x08, 0x8e);
|
||||
setup_idt_entry(37,(u32)irq_handler_5,0x08, 0x8e);
|
||||
setup_idt_entry(38,(u32)irq_handler_6,0x08, 0x8e);
|
||||
setup_idt_entry(39,(u32)irq_handler_7,0x08, 0x8e);
|
||||
setup_idt_entry(40,(u32)irq_handler_8,0x08, 0x8e);
|
||||
setup_idt_entry(41,(u32)irq_handler_9,0x08, 0x8e);
|
||||
setup_idt_entry(42,(u32)irq_handler_10,0x08, 0x8e);
|
||||
setup_idt_entry(43,(u32)irq_handler_11,0x08, 0x8e);
|
||||
setup_idt_entry(44,(u32)irq_handler_12,0x08, 0x8e);
|
||||
setup_idt_entry(45,(u32)irq_handler_13,0x08, 0x8e);
|
||||
setup_idt_entry(46,(u32)irq_handler_14,0x08, 0x8e);
|
||||
setup_idt_entry(47,(u32)irq_handler_15,0x08, 0x8e);
|
||||
// Enable interrupt flags
|
||||
__asm__ __volatile__("sti");
|
||||
}
|
||||
55
components/interrupts/interrupts.h
Normal file
55
components/interrupts/interrupts.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef INTERRUPTS_H
|
||||
#define INTERRUPTS_H
|
||||
#include "types.h"
|
||||
|
||||
// There are more interrupts but tbh i doubt we're going to need them
|
||||
#define i_Timer 0
|
||||
#define i_Keyboard 1
|
||||
#define i_PIC2 2
|
||||
#define i_COM2 3
|
||||
#define i_COM1 4
|
||||
#define i_LPT2 5
|
||||
|
||||
|
||||
struct cpu_reg_state {
|
||||
u32 gs, fs, es, ds; // segment registers
|
||||
u32 edi, esi, ebp, esp; // generaal purupose via pushad
|
||||
u32 ebx, edx, ecx, eax;
|
||||
u32 int_no, err_code; // pushed by each interrupt dispatcher
|
||||
u32 eip, cs, eflags, useresp, ss; // processor pushes this automatically
|
||||
}__attribute__((packed)); // we shouldn't need packing since everythign is dwords here
|
||||
|
||||
|
||||
#define IDT_SIZE 256
|
||||
|
||||
struct IDT_Entry {
|
||||
u16 offset_low; // offset bits 0..15
|
||||
u16 selector; // code segment in either gdt or ldt
|
||||
u8 zero; // not used always 0
|
||||
/* 7 0
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* | P | DPL | S | GateType |
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
u8 type_attrs; // format specified above
|
||||
u16 offset_high;// offset bits 16..31
|
||||
}__attribute__((packed));
|
||||
|
||||
struct IDT_PTR {
|
||||
u16 limit;
|
||||
u32 address;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct IDT_Entry IDT[IDT_SIZE];
|
||||
struct IDT_PTR idt_ptr;
|
||||
|
||||
void init_idt();
|
||||
void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs);
|
||||
void int_keyboard(struct cpu_reg_state*);
|
||||
void interrupt_handler(struct cpu_reg_state*);
|
||||
|
||||
|
||||
// IRQ specifi functions
|
||||
void init_irq_handler(u32 irq, void (*handler)(struct cpu_reg_state* cpu));
|
||||
void irq_handler(struct cpu_reg_state* cpu);
|
||||
#endif
|
||||
73
components/kbd/kbd.c
Normal file
73
components/kbd/kbd.c
Normal file
@@ -0,0 +1,73 @@
|
||||
// US Keyboard layout because 'Murrica
|
||||
#include "kbd.h"
|
||||
#include "ports.h"
|
||||
#include "pit.h"
|
||||
#include "serial.h"
|
||||
#include "types.h"
|
||||
#include "stlio.h"
|
||||
|
||||
|
||||
// Courtesy of http://www.osdever.net/bkerndev/Docs/keyboard.htm
|
||||
unsigned char keymap[128] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
||||
'9', '0', '-', '=', '\b', /* Backspace */
|
||||
'\t', /* Tab */
|
||||
'q', 'w', 'e', 'r', /* 19 */
|
||||
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
|
||||
0, /* 29 - Control */
|
||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
|
||||
'\'', '`', 0, /* Left shift */
|
||||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
||||
'm', ',', '.', '/', 0, /* Right shift */
|
||||
'*',
|
||||
0, /* Alt */
|
||||
' ', /* Space bar */
|
||||
0, /* Caps lock */
|
||||
0, /* 59 - F1 key ... > */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, /* < ... F10 */
|
||||
0, /* 69 - Num lock*/
|
||||
0, /* Scroll Lock */
|
||||
0, /* Home key */
|
||||
0, /* Up Arrow */
|
||||
0, /* Page Up */
|
||||
'-',
|
||||
0, /* Left Arrow */
|
||||
0,
|
||||
0, /* Right Arrow */
|
||||
'+',
|
||||
0, /* 79 - End key*/
|
||||
0, /* Down Arrow */
|
||||
0, /* Page Down */
|
||||
0, /* Insert Key */
|
||||
0, /* Delete Key */
|
||||
0, 0, 0,
|
||||
0, /* F11 Key */
|
||||
0, /* F12 Key */
|
||||
0, /* All other keys are undefined */
|
||||
};
|
||||
|
||||
|
||||
// Reads one key from the keyboard
|
||||
void kbd_read_key(__attribute__((unused)) struct cpu_reg_state* cpu) {
|
||||
u8 scancode = serial_read_byte(KBD_PORT);
|
||||
if(scancode & 0x80) {
|
||||
// Key released
|
||||
kbd_key = keymap[scancode & 0x7f]; // clamp to 127 as the max val(gcc is anoying)
|
||||
kbd_state = KBD_RELEASE;
|
||||
kbd_time = pit_timer_ticks;
|
||||
}
|
||||
else {
|
||||
// Key pressed
|
||||
kbd_key = keymap[scancode & 0x7f]; // clamp to 127 as the max val(gcc is anoying)
|
||||
kbd_state = KBD_PRESS;
|
||||
kbd_time = pit_timer_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void kbd_install_keyboard(void) {
|
||||
init_irq_handler(1, kbd_read_key);
|
||||
kbd_key = '\0';
|
||||
kbd_state = 0;
|
||||
kbd_time = 0;
|
||||
}
|
||||
20
components/kbd/kbd.h
Normal file
20
components/kbd/kbd.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef KBD_H
|
||||
#define KBD_H
|
||||
#include "types.h"
|
||||
#include "interrupts.h"
|
||||
#include "framebuffer.h"
|
||||
|
||||
#define KBD_PORT 0x60
|
||||
|
||||
#define KBD_PRESS 1
|
||||
#define KBD_WAITING 2
|
||||
#define KBD_RELEASE 0x80
|
||||
|
||||
char kbd_key;
|
||||
u8 kbd_state;
|
||||
u32 kbd_time;
|
||||
|
||||
void kbd_install_keyboard(void);
|
||||
|
||||
void kbd_read_key(struct cpu_reg_state* cpu);
|
||||
#endif
|
||||
18
components/mem/mem.c
Normal file
18
components/mem/mem.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "mem.h"
|
||||
#include "types.h"
|
||||
|
||||
u32 memcpy(u8* src, u8* dest, const u32 size) {
|
||||
u32 i;
|
||||
for(i =0; i < size+1;i++) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
u32 memset(u8* buf, const u8 val, const u32 size) {
|
||||
u32 i;
|
||||
for(i=0;i<size;i++) {
|
||||
buf[i] = val;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
5
components/mem/mem.h
Normal file
5
components/mem/mem.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "types.h"
|
||||
|
||||
u32 memcpy(u8* src, u8* dest, const u32 size);
|
||||
|
||||
u32 memset(u8* buf, const u8 val, const u32 size);
|
||||
19
components/pit/pit.c
Normal file
19
components/pit/pit.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "pit.h"
|
||||
#include "types.h"
|
||||
#include "interrupts.h"
|
||||
#include "serial.h"
|
||||
#include "stlio.h"
|
||||
|
||||
void pit_inc_ticks(__attribute__((unused)) struct cpu_reg_state* cpu) {
|
||||
pit_timer_ticks++;
|
||||
}
|
||||
|
||||
void pit_timer_wait(u32 time) {
|
||||
u32 ticks = time + pit_timer_ticks;
|
||||
while(pit_timer_ticks < ticks);
|
||||
}
|
||||
|
||||
void pit_install_timer(void) {
|
||||
init_irq_handler(0, pit_inc_ticks); // timer interrupt request falls into irq 0
|
||||
pit_timer_ticks = 0;
|
||||
}
|
||||
19
components/pit/pit.h
Normal file
19
components/pit/pit.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef PIT_H
|
||||
#define PIT_H
|
||||
#include "interrupts.h"
|
||||
#include "types.h"
|
||||
|
||||
// 60hz timer for now
|
||||
#define PIT_TIMER_INTERVAL 100
|
||||
#define PIT_TIME_DATA0 0x40
|
||||
#define PIT_TIME_DATA1 0x41
|
||||
#define PIT_TIME_DATA2 0x42
|
||||
|
||||
volatile u32 pit_timer_ticks;
|
||||
|
||||
void pit_inc_ticks(struct cpu_reg_state*);
|
||||
|
||||
void pit_timer_wait(u32);
|
||||
|
||||
void pit_install_timer(void);
|
||||
#endif
|
||||
9
components/ports/ports.h
Normal file
9
components/ports/ports.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "types.h"
|
||||
|
||||
#ifndef INCLUDE_IO_H
|
||||
#define INCLUDE_IO_H
|
||||
|
||||
void serialport_write_byte(const u16, const u16);
|
||||
|
||||
u8 serial_read_byte(const u16);
|
||||
#endif /* INCLUDE_IO_H */
|
||||
21
components/ports/ports.s
Normal file
21
components/ports/ports.s
Normal file
@@ -0,0 +1,21 @@
|
||||
; Helpers for serial ports which pretty much have to to be
|
||||
; written in asm
|
||||
|
||||
global serialport_write_byte
|
||||
global serial_read_byte
|
||||
|
||||
; write a byte
|
||||
;serialport_write_byte
|
||||
serialport_write_byte:
|
||||
mov al, [esp+8]
|
||||
mov dx, [esp+4]
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
; Read byte from serial port
|
||||
;serialport_read_byte
|
||||
serial_read_byte:
|
||||
mov dx, [esp + 4] ; grab the address of the targeted port
|
||||
in al, dx ; read byte from the port
|
||||
ret
|
||||
|
||||
6
components/readme.md
Normal file
6
components/readme.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Components Library
|
||||
|
||||
These are the smaller components that give the kernel actual behaviors.
|
||||
These are pieces that are *practically* required for the OS to function at a
|
||||
basic level but otherwise are not *technically* required for sheer load-level
|
||||
operations.
|
||||
89
components/serial/serial.c
Normal file
89
components/serial/serial.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "serial.h"
|
||||
|
||||
/*
|
||||
* SERIAL_LINE_COMMAND_PORT configuration
|
||||
* Bit: | 7 | 6 | 5 4 3 | 2 | 1 0 |
|
||||
* Content: | d | b | prty | s | dl |
|
||||
* d = enable/disable DLAB
|
||||
* b = enable/disable break control
|
||||
* prty = # of parity bits to use
|
||||
* s = # no of stop bits [0 is 1] and [1 is 1.5 or 2]
|
||||
* dl = length of data
|
||||
*
|
||||
*/
|
||||
|
||||
void serial_set_baud_rate(const u16 com_port, const u16 divisor) {
|
||||
// Activate line - ready to send higher 8 bits of data
|
||||
// send the higher 8 bits first
|
||||
// send the lower 8 bits next
|
||||
|
||||
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(com_port),
|
||||
SERIAL_LINE_ENABLE);
|
||||
|
||||
serialport_write_byte(SERIAL_DATA_PORT(com_port),
|
||||
(divisor>>8) & 0x00ff);
|
||||
|
||||
serialport_write_byte(SERIAL_DATA_PORT(com_port),
|
||||
divisor & 0x00ff);
|
||||
}
|
||||
|
||||
// Payload described above
|
||||
void serial_configure_line(const u16 line, const u8 payload) {
|
||||
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(line), payload);
|
||||
}
|
||||
|
||||
|
||||
u8 serial_fifo_empty(const u16 com_port) {
|
||||
// we get back 0x20 if it is empty
|
||||
return serial_read_byte(SERIAL_LINE_STATUS_PORT(com_port)) &
|
||||
SERIAL_FIFO_EMPTY_CODE;
|
||||
}
|
||||
|
||||
u64 serial_write(const char* buffer, const u64 size) {
|
||||
/*
|
||||
* Writes a given buffer to the com1 serial port for debugging in bochs
|
||||
*/
|
||||
serialport_write_byte(SERIAL_DATA_PORT_INT_EN(SERIAL_COM1_BASE),
|
||||
0x00);
|
||||
|
||||
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(SERIAL_COM1_BASE),
|
||||
SERIAL_LINE_ENABLE);
|
||||
|
||||
// quarter speed hopefully the fifo quue wont fill this way
|
||||
serialport_write_byte(SERIAL_COM1_BASE,
|
||||
0x01);
|
||||
|
||||
serialport_write_byte(SERIAL_DATA_PORT_INT_EN(SERIAL_COM1_BASE),
|
||||
0x00);
|
||||
|
||||
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(SERIAL_COM1_BASE),
|
||||
SERIAL_DEFAULT_LINE_CFG);
|
||||
|
||||
serialport_write_byte(SERIAL_FIFO_COMMAND_PORT(SERIAL_COM1_BASE),
|
||||
SERIAL_DEFAULT_BUFFER_CFG);
|
||||
|
||||
serialport_write_byte(SERIAL_MODEM_COMMAND_PORT(SERIAL_COM1_BASE),
|
||||
0x0B);
|
||||
|
||||
u64 idx;
|
||||
for(idx =0; idx < size; idx++) {
|
||||
serialport_write_byte(SERIAL_COM1_BASE, buffer[idx]);
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
void serial_pic_ack(u32 interrupt) {
|
||||
// ignore things that are too small and too big
|
||||
if(interrupt < PIC1_START_INT || interrupt > PIC2_END_INT) {
|
||||
return;
|
||||
}
|
||||
// Send acknoldgement to the pic that we have handled the interrupt
|
||||
// without this it literally just wait for the ack
|
||||
if(interrupt < PIC2_START_INT) {
|
||||
serialport_write_byte(PIC1_PORT, PIC_ACK);
|
||||
}
|
||||
else {
|
||||
serialport_write_byte(PIC2_PORT, PIC_ACK);
|
||||
}
|
||||
}
|
||||
43
components/serial/serial.h
Normal file
43
components/serial/serial.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "types.h"
|
||||
#include "ports.h"
|
||||
|
||||
// Serial driver interface
|
||||
|
||||
#define SERIAL_COM1_BASE 0x03F8
|
||||
|
||||
#define SERIAL_DATA_PORT(base) (base)
|
||||
#define SERIAL_DATA_PORT_INT_EN(base) (base+1)
|
||||
#define SERIAL_FIFO_COMMAND_PORT(base) (base+2)
|
||||
#define SERIAL_LINE_COMMAND_PORT(base) (base+3)
|
||||
#define SERIAL_MODEM_COMMAND_PORT(base) (base+4)
|
||||
#define SERIAL_LINE_STATUS_PORT(base) (base+5)
|
||||
|
||||
#define SERIAL_LINE_ENABLE 0x80
|
||||
|
||||
// Default configurations for serial ports/lines/buffers etc.
|
||||
// Rational can be found here: https://littleosbook.github.io/#configuring-the-buffers
|
||||
#define SERIAL_DEFAULT_LINE_CFG 0x03
|
||||
#define SERIAL_DEFAULT_BUFFER_CFG 0xc7
|
||||
#define SERIAL_DEFAULT_MODEM_CFG 0x03
|
||||
|
||||
#define SERIAL_FIFO_EMPTY_CODE 0x20
|
||||
|
||||
#define PIC1_PORT 0x20
|
||||
#define PIC2_PORT 0xA0
|
||||
|
||||
#define PIC1_START_INT 0x20
|
||||
#define PIC1_END_INT 0x27
|
||||
#define PIC2_START_INT 0x28
|
||||
#define PIC2_END_INT 0x2F
|
||||
|
||||
#define PIC_ACK 0x20
|
||||
|
||||
void serial_set_baud_rate(const u16, const u16);
|
||||
|
||||
void serial_configure_line(const u16, const u8);
|
||||
|
||||
u8 serial_fifo_empty(const u16);
|
||||
|
||||
u64 serial_write(const char* buffer, const u64 size);
|
||||
|
||||
void serial_pic_ack(u32 interrupt);
|
||||
31
components/tests/tests.c
Normal file
31
components/tests/tests.c
Normal file
@@ -0,0 +1,31 @@
|
||||
// Module for testing drivers and other things
|
||||
#include "stlio.h"
|
||||
#include "tests.h"
|
||||
#include "serial.h"
|
||||
#include "shell.h"
|
||||
|
||||
void test_serial_write() {
|
||||
char* serial1 = "0123456789abcdef0123456789abcdef";
|
||||
serial_write(serial1, strlen(serial1));
|
||||
printf("serial test write finished\n");
|
||||
}
|
||||
|
||||
void test_write(void) {
|
||||
char* msg1 = "Writing to fbout\n";
|
||||
printf(msg1);
|
||||
}
|
||||
|
||||
void test_dispatcher(void) {
|
||||
clear_fb();
|
||||
}
|
||||
void test_read(void) {
|
||||
char buf[5];
|
||||
u32 bread = read(buf, 5);
|
||||
printf("Bytes read: "); printhex(bread);
|
||||
printf("\n");
|
||||
printf("String read: "); printf(buf);
|
||||
printf("\n");
|
||||
for(u32 i = 0;i<5;i++) {
|
||||
printhex(buf[i]); printf(" ");
|
||||
}
|
||||
}
|
||||
6
components/tests/tests.h
Normal file
6
components/tests/tests.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "types.h"
|
||||
#include "stlio.h"
|
||||
|
||||
void test_write(void);
|
||||
void test_dispatcher(void);
|
||||
void test_read(void);
|
||||
16
components/types/types.h
Normal file
16
components/types/types.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned long u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed long s32;
|
||||
typedef signed long long s64;
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
#define NULL 0
|
||||
#endif
|
||||
Reference in New Issue
Block a user