diff --git a/Makefile b/Makefile index 96c7aa1..5e26c5c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC = i386-elf-gcc LD = i386-elf-ld AS = nasm -CFLAGS = -ffreestanding -fno-builtin -fno-stack-protector -nostdinc -mgeneral-regs-only -m32 -march=i386 -Iinclude -Wall +CFLAGS = -ffreestanding -fno-builtin -fno-stack-protector -nostdinc -mgeneral-regs-only -m32 -march=i386 -Iinclude -Wall SRC = ./src BUILD = ./build diff --git a/notes.txt b/docs/memory.txt similarity index 100% rename from notes.txt rename to docs/memory.txt diff --git a/docs/syscalls.txt b/docs/syscalls.txt new file mode 100644 index 0000000..3b77ed5 --- /dev/null +++ b/docs/syscalls.txt @@ -0,0 +1,11 @@ +=== System Calls === + +Syscall handlers are prefixed by 'sys_' +Syscalls can be called using interrupt 0x80 +The EAX register should countain a syscall number + +Here's a list of syscalls: (and their numbers) + +syscall(0) : Sleep() + Args: EBX - Number of miliseconds to sleep for + diff --git a/include/pit.h b/include/pit.h new file mode 100644 index 0000000..474bedf --- /dev/null +++ b/include/pit.h @@ -0,0 +1,47 @@ +#ifndef TIMER_H +#define TIMER_H + +#include +#include +#include +#include + +#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2 +#define COMMAND 0x43 +#define INPUT_CLK 1193182 + +static uint32_t* timerTicks = (uint32_t*)0x1000; + +__attribute__ ((interrupt)) +void timerHandler(intFrame_t* iframe) { + *timerTicks += 1; + + // TODO: Improve the cursor rendering + if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y); + else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y); + + sendPicEOI(0); +} + +void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) { + if (channel > 2 || opMode > 7) { return; } + __asm__ volatile ("cli"); + + // Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86 + outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1))); + + // Send frequency + uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out + outb(CHANNEL_0 + channel, (uint8_t)freq); + outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8)); + + __asm__ volatile ("sti"); +} + +void setupTimer() { // Sets up IRQ 0 - PIT + idtSetGate(0x20, timerHandler, INT_GATE_FLAGS); + unsetIrqMask(0); + setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms +} + +#endif diff --git a/include/syscall.h b/include/syscall.h index 5eebb1b..7fbd540 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -1,27 +1,25 @@ #ifndef SYSCALL_H #define SYSCALL_H -#include +#include // System call count #define MAX_SYSCALLS 2 -void sys_test0() { - fgColor = YELLOW; - print("Syscall 0 - Test\n"); - fgColor = FG_COLOR; -} +// Args: ebx - number of miliseconds +void sys_sleep() { + uint32_t ms; + __asm__ volatile ("movl %%ebx, %0" : "=r"(ms)); -void sys_test1() { - fgColor = CYAN; - print("Syscall 1 - Test\n"); - fgColor = FG_COLOR; + uint32_t requiredTicks = *timerTicks + ms; + while (*timerTicks != requiredTicks) { // Wait... + __asm__ volatile ("sti;hlt;cli;"); + } } // System call table void* syscalls[MAX_SYSCALLS] = { - sys_test0, - sys_test1, + sys_sleep, }; // int 0x80 - Syscall interrupt, handled by this function diff --git a/include/time.h b/include/time.h new file mode 100644 index 0000000..e6a193d --- /dev/null +++ b/include/time.h @@ -0,0 +1,8 @@ +#ifndef TIME_H +#define TIME_H + +void sleep(uint32_t ms) { + __asm__ volatile ("int $0x80" : : "a"(0), "b"(ms)); +} + +#endif diff --git a/include/timer.h b/include/timer.h index be75a3b..474bedf 100644 --- a/include/timer.h +++ b/include/timer.h @@ -4,43 +4,44 @@ #include #include #include -#include #include -#define INPUT_CLK 1193180 +#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2 +#define COMMAND 0x43 +#define INPUT_CLK 1193182 -uint32_t timerTicks = 0; +static uint32_t* timerTicks = (uint32_t*)0x1000; __attribute__ ((interrupt)) void timerHandler(intFrame_t* iframe) { - timerTicks++; + *timerTicks += 1; // TODO: Improve the cursor rendering - if (timerTicks % 500 == 0) putcAt(127, cursor.x, cursor.y); - else if (timerTicks % 250 == 0) putcAt(' ', cursor.x, cursor.y); + if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y); + else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y); sendPicEOI(0); } -void setupTimer() { - idtSetGate(32, timerHandler, INT_GATE_FLAGS); - unsetIrqMask(0); -} +void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) { + if (channel > 2 || opMode > 7) { return; } + __asm__ volatile ("cli"); -// Source: https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interval_Timer -void timerPhase(uint32_t hz) { - uint16_t div = INPUT_CLK / hz; + // Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86 + outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1))); - outb(0x43, 0x36); // Tell PIT that we're setting channel 0 - outb(0x40, div & 0xff); // Low byte - outb(0x40, div >> 8); // High byte -} - -void sleep(uint32_t ticks) { - uint32_t eticks = ticks + timerTicks; + // Send frequency + uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out + outb(CHANNEL_0 + channel, (uint8_t)freq); + outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8)); - while (timerTicks != eticks); // Should ignore overflows unlike '<' + __asm__ volatile ("sti"); } +void setupTimer() { // Sets up IRQ 0 - PIT + idtSetGate(0x20, timerHandler, INT_GATE_FLAGS); + unsetIrqMask(0); + setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms +} #endif diff --git a/src/fonts/term16n.asm b/src/fonts/term16n.asm index 6a793cd..1ec136d 100644 --- a/src/fonts/term16n.asm +++ b/src/fonts/term16n.asm @@ -1526,22 +1526,22 @@ db 00h,\ 00h,\ 00h,\ 00h -db 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 00h,\ - 0FEh +db 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF,\ + 0xFF ;; End of visible ascii characters times 2048-($-$$) db 0 diff --git a/src/kernel.c b/src/kernel.c index d5d6183..f341287 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -9,7 +9,8 @@ #include #include #include -#include +#include +#include #define PROMPT "#> " @@ -54,7 +55,6 @@ void main() { __asm__ volatile ("sti"); setupTimer(); - timerPhase(1000); // 1 kHz setupKeyboard(); // Run Interactive Shell Program @@ -166,7 +166,7 @@ void main() { drawCircle(1500, 600, 300, WHITE); fillCircle(950, 750, 75, rgb(0xa2, 0xd6, 0xf9)); - //read('q'); // Wait until we get a 'q' + read('q'); // Wait until we get a 'q' clear(); } else if (strcmp(input, "help") == 0) { print("Available Commands:\n"); @@ -179,6 +179,7 @@ void main() { print(" ls | Lists all available files\n"); print(" memmap | Prints the memory map and info\n"); print(" reboot | Reboots the system\n"); + print(" sleep | Sleeps for input number of seconds\n"); print(" test | Performs tests\n"); } else if (strcmp(input, "ls") == 0) { printFiletable(filetable); @@ -186,6 +187,13 @@ void main() { printPhysicalMemmap(); } else if (strcmp(input, "reboot") == 0) { outb(0x64, 0xFE); + } else if (strcmp(input, "sleep") == 0) { + if (*args == '\0') continue; + + uint32_t ms = atoi(args) * 1000; // Convert seconds to miliseconds + if (ms == 0) continue; + + sleep(ms); } else if (strcmp(input, "test") == 0) { print("Running Tests...\n"); uint8_t buf[512]; @@ -206,9 +214,6 @@ void main() { } else { print("[ FAIL ]\n"); } - print("Syscall Test:\n"); - __asm__ volatile ("movl $0, %eax; int $0x80"); // Syscall(0); - __asm__ volatile ("movl $1, %eax; int $0x80"); // Syscall(1); print("\nTests Finished!\n"); } else { diff --git a/todo.txt b/todo.txt index 4b175e1..5a68d9c 100644 --- a/todo.txt +++ b/todo.txt @@ -9,10 +9,11 @@ Legend: - [x] Multistage Bootloader - [ ] Bootloader reads filetable to find files +- [ ] The almighty 'printf()' - [!] Makefile refactorin' - [x] Write down where stuff is in memory (in notes.txt) - [ ] "Text" mode (not actually) - - [ ] Scrolling + - [x] Scrolling - [ ] Scroll-back - [ ] Color codes (and just multicolor text in general) - [x] VESA BIOS Extensions @@ -34,12 +35,15 @@ Legend: - [x] Triangles (3D?!!???) - [x] Rectange :) - [x] Circle! - - [_] Filled verisons -- [ ] Interrupts + - [x] Filled verisons +- [ ] Interrupts - [x] IDT Setup (idt.h) - [x] Exception handling - - [ ] Hardware/software interrupts - - [ ] Syscalls! (int 0x80) + - [x] Hardware/software interrupts + - [x] Syscalls! (int 0x80) + - [ ] IRQ 0 - PIT + - [ ] IRQ 1 - Keyboard + - [ ] IRQ 8 - CMOS Real time clock - [ ] Math - [ ] Trigonometry - [ ] Sine @@ -63,6 +67,7 @@ Legend: - [ ] NAN - [x] E (eulers number) - [x] PI + - [ ] Floating point macros/functions - [ ] Filesystem - [ ] Utility for filesystem building (not just an assembly file) - [x] Filetable @@ -77,6 +82,7 @@ Legend: - [ ] Symbolic - [ ] Hard - [ ] System Calls + - [ ] Sleep() - [ ] Write() - [ ] Read() - [ ] Open() @@ -103,7 +109,6 @@ Legend: - [ ] stdin - [ ] stdout - [ ] stderr - - [ ] printf - [ ] Memory manager - [x] Memory map - [x] Print mem map