forked from PoliEcho-holding-org/kern
Reimplemented PIT Timer. Sleep is now a syscall. Also made docs/ that contains some info so i don't forget.
This commit is contained in:
@@ -3,7 +3,7 @@ CC = i386-elf-gcc
|
|||||||
LD = i386-elf-ld
|
LD = i386-elf-ld
|
||||||
AS = nasm
|
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
|
SRC = ./src
|
||||||
BUILD = ./build
|
BUILD = ./build
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef TIMER_H
|
||||||
|
#define TIMER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <idt.h>
|
||||||
|
#include <pic.h>
|
||||||
|
#include <screen.h>
|
||||||
|
|
||||||
|
#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
|
||||||
+10
-12
@@ -1,27 +1,25 @@
|
|||||||
#ifndef SYSCALL_H
|
#ifndef SYSCALL_H
|
||||||
#define SYSCALL_H
|
#define SYSCALL_H
|
||||||
|
|
||||||
#include <screen.h>
|
#include <pit.h>
|
||||||
|
|
||||||
// System call count
|
// System call count
|
||||||
#define MAX_SYSCALLS 2
|
#define MAX_SYSCALLS 2
|
||||||
|
|
||||||
void sys_test0() {
|
// Args: ebx - number of miliseconds
|
||||||
fgColor = YELLOW;
|
void sys_sleep() {
|
||||||
print("Syscall 0 - Test\n");
|
uint32_t ms;
|
||||||
fgColor = FG_COLOR;
|
__asm__ volatile ("movl %%ebx, %0" : "=r"(ms));
|
||||||
}
|
|
||||||
|
|
||||||
void sys_test1() {
|
uint32_t requiredTicks = *timerTicks + ms;
|
||||||
fgColor = CYAN;
|
while (*timerTicks != requiredTicks) { // Wait...
|
||||||
print("Syscall 1 - Test\n");
|
__asm__ volatile ("sti;hlt;cli;");
|
||||||
fgColor = FG_COLOR;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// System call table
|
// System call table
|
||||||
void* syscalls[MAX_SYSCALLS] = {
|
void* syscalls[MAX_SYSCALLS] = {
|
||||||
sys_test0,
|
sys_sleep,
|
||||||
sys_test1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// int 0x80 - Syscall interrupt, handled by this function
|
// int 0x80 - Syscall interrupt, handled by this function
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef TIME_H
|
||||||
|
#define TIME_H
|
||||||
|
|
||||||
|
void sleep(uint32_t ms) {
|
||||||
|
__asm__ volatile ("int $0x80" : : "a"(0), "b"(ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+22
-21
@@ -4,43 +4,44 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <idt.h>
|
#include <idt.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
#include <system.h>
|
|
||||||
#include <screen.h>
|
#include <screen.h>
|
||||||
|
|
||||||
#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))
|
__attribute__ ((interrupt))
|
||||||
void timerHandler(intFrame_t* iframe) {
|
void timerHandler(intFrame_t* iframe) {
|
||||||
timerTicks++;
|
*timerTicks += 1;
|
||||||
|
|
||||||
// TODO: Improve the cursor rendering
|
// TODO: Improve the cursor rendering
|
||||||
if (timerTicks % 500 == 0) putcAt(127, cursor.x, cursor.y);
|
if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y);
|
||||||
else if (timerTicks % 250 == 0) putcAt(' ', cursor.x, cursor.y);
|
else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y);
|
||||||
|
|
||||||
sendPicEOI(0);
|
sendPicEOI(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTimer() {
|
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
|
||||||
idtSetGate(32, timerHandler, INT_GATE_FLAGS);
|
if (channel > 2 || opMode > 7) { return; }
|
||||||
unsetIrqMask(0);
|
__asm__ volatile ("cli");
|
||||||
}
|
|
||||||
|
|
||||||
// Source: https://en.wikibooks.org/wiki/X86_Assembly/Programmable_Interval_Timer
|
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
|
||||||
void timerPhase(uint32_t hz) {
|
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
|
||||||
uint16_t div = INPUT_CLK / hz;
|
|
||||||
|
|
||||||
outb(0x43, 0x36); // Tell PIT that we're setting channel 0
|
// Send frequency
|
||||||
outb(0x40, div & 0xff); // Low byte
|
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
|
||||||
outb(0x40, div >> 8); // High byte
|
outb(CHANNEL_0 + channel, (uint8_t)freq);
|
||||||
}
|
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
|
||||||
|
|
||||||
void sleep(uint32_t ticks) {
|
|
||||||
uint32_t eticks = ticks + timerTicks;
|
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
|||||||
+16
-16
@@ -1526,22 +1526,22 @@ db 00h,\
|
|||||||
00h,\
|
00h,\
|
||||||
00h,\
|
00h,\
|
||||||
00h
|
00h
|
||||||
db 00h,\
|
db 0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
00h,\
|
0xFF,\
|
||||||
0FEh
|
0xFF
|
||||||
|
|
||||||
;; End of visible ascii characters
|
;; End of visible ascii characters
|
||||||
times 2048-($-$$) db 0
|
times 2048-($-$$) db 0
|
||||||
|
|||||||
+11
-6
@@ -9,7 +9,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <graphics.h>
|
#include <graphics.h>
|
||||||
#include <keyboard.h>
|
#include <keyboard.h>
|
||||||
#include <timer.h>
|
#include <pit.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define PROMPT "#> "
|
#define PROMPT "#> "
|
||||||
|
|
||||||
@@ -54,7 +55,6 @@ void main() {
|
|||||||
__asm__ volatile ("sti");
|
__asm__ volatile ("sti");
|
||||||
|
|
||||||
setupTimer();
|
setupTimer();
|
||||||
timerPhase(1000); // 1 kHz
|
|
||||||
setupKeyboard();
|
setupKeyboard();
|
||||||
|
|
||||||
// Run Interactive Shell Program
|
// Run Interactive Shell Program
|
||||||
@@ -166,7 +166,7 @@ void main() {
|
|||||||
drawCircle(1500, 600, 300, WHITE);
|
drawCircle(1500, 600, 300, WHITE);
|
||||||
fillCircle(950, 750, 75, rgb(0xa2, 0xd6, 0xf9));
|
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();
|
clear();
|
||||||
} else if (strcmp(input, "help") == 0) {
|
} else if (strcmp(input, "help") == 0) {
|
||||||
print("Available Commands:\n");
|
print("Available Commands:\n");
|
||||||
@@ -179,6 +179,7 @@ void main() {
|
|||||||
print(" ls | Lists all available files\n");
|
print(" ls | Lists all available files\n");
|
||||||
print(" memmap | Prints the memory map and info\n");
|
print(" memmap | Prints the memory map and info\n");
|
||||||
print(" reboot | Reboots the system\n");
|
print(" reboot | Reboots the system\n");
|
||||||
|
print(" sleep | Sleeps for input number of seconds\n");
|
||||||
print(" test | Performs tests\n");
|
print(" test | Performs tests\n");
|
||||||
} else if (strcmp(input, "ls") == 0) {
|
} else if (strcmp(input, "ls") == 0) {
|
||||||
printFiletable(filetable);
|
printFiletable(filetable);
|
||||||
@@ -186,6 +187,13 @@ void main() {
|
|||||||
printPhysicalMemmap();
|
printPhysicalMemmap();
|
||||||
} else if (strcmp(input, "reboot") == 0) {
|
} else if (strcmp(input, "reboot") == 0) {
|
||||||
outb(0x64, 0xFE);
|
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) {
|
} else if (strcmp(input, "test") == 0) {
|
||||||
print("Running Tests...\n");
|
print("Running Tests...\n");
|
||||||
uint8_t buf[512];
|
uint8_t buf[512];
|
||||||
@@ -206,9 +214,6 @@ void main() {
|
|||||||
} else {
|
} else {
|
||||||
print("[ FAIL ]\n");
|
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");
|
print("\nTests Finished!\n");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ Legend:
|
|||||||
|
|
||||||
- [x] Multistage Bootloader
|
- [x] Multistage Bootloader
|
||||||
- [ ] Bootloader reads filetable to find files
|
- [ ] Bootloader reads filetable to find files
|
||||||
|
- [ ] The almighty 'printf()'
|
||||||
- [!] Makefile refactorin'
|
- [!] Makefile refactorin'
|
||||||
- [x] Write down where stuff is in memory (in notes.txt)
|
- [x] Write down where stuff is in memory (in notes.txt)
|
||||||
- [ ] "Text" mode (not actually)
|
- [ ] "Text" mode (not actually)
|
||||||
- [ ] Scrolling
|
- [x] Scrolling
|
||||||
- [ ] Scroll-back
|
- [ ] Scroll-back
|
||||||
- [ ] Color codes (and just multicolor text in general)
|
- [ ] Color codes (and just multicolor text in general)
|
||||||
- [x] VESA BIOS Extensions
|
- [x] VESA BIOS Extensions
|
||||||
@@ -34,12 +35,15 @@ Legend:
|
|||||||
- [x] Triangles (3D?!!???)
|
- [x] Triangles (3D?!!???)
|
||||||
- [x] Rectange :)
|
- [x] Rectange :)
|
||||||
- [x] Circle!
|
- [x] Circle!
|
||||||
- [_] Filled verisons
|
- [x] Filled verisons
|
||||||
- [ ] Interrupts
|
- [ ] Interrupts
|
||||||
- [x] IDT Setup (idt.h)
|
- [x] IDT Setup (idt.h)
|
||||||
- [x] Exception handling
|
- [x] Exception handling
|
||||||
- [ ] Hardware/software interrupts
|
- [x] Hardware/software interrupts
|
||||||
- [ ] Syscalls! (int 0x80)
|
- [x] Syscalls! (int 0x80)
|
||||||
|
- [ ] IRQ 0 - PIT
|
||||||
|
- [ ] IRQ 1 - Keyboard
|
||||||
|
- [ ] IRQ 8 - CMOS Real time clock
|
||||||
- [ ] Math
|
- [ ] Math
|
||||||
- [ ] Trigonometry
|
- [ ] Trigonometry
|
||||||
- [ ] Sine
|
- [ ] Sine
|
||||||
@@ -63,6 +67,7 @@ Legend:
|
|||||||
- [ ] NAN
|
- [ ] NAN
|
||||||
- [x] E (eulers number)
|
- [x] E (eulers number)
|
||||||
- [x] PI
|
- [x] PI
|
||||||
|
- [ ] Floating point macros/functions
|
||||||
- [ ] Filesystem
|
- [ ] Filesystem
|
||||||
- [ ] Utility for filesystem building (not just an assembly file)
|
- [ ] Utility for filesystem building (not just an assembly file)
|
||||||
- [x] Filetable
|
- [x] Filetable
|
||||||
@@ -77,6 +82,7 @@ Legend:
|
|||||||
- [ ] Symbolic
|
- [ ] Symbolic
|
||||||
- [ ] Hard
|
- [ ] Hard
|
||||||
- [ ] System Calls
|
- [ ] System Calls
|
||||||
|
- [ ] Sleep()
|
||||||
- [ ] Write()
|
- [ ] Write()
|
||||||
- [ ] Read()
|
- [ ] Read()
|
||||||
- [ ] Open()
|
- [ ] Open()
|
||||||
@@ -103,7 +109,6 @@ Legend:
|
|||||||
- [ ] stdin
|
- [ ] stdin
|
||||||
- [ ] stdout
|
- [ ] stdout
|
||||||
- [ ] stderr
|
- [ ] stderr
|
||||||
- [ ] printf
|
|
||||||
- [ ] Memory manager
|
- [ ] Memory manager
|
||||||
- [x] Memory map
|
- [x] Memory map
|
||||||
- [x] Print mem map
|
- [x] Print mem map
|
||||||
|
|||||||
Reference in New Issue
Block a user