kernel: add timers via pit
This commit is contained in:
parent
e698cfdfd1
commit
02e855c066
8 changed files with 172 additions and 1 deletions
|
|
@ -36,3 +36,5 @@ enum fs_access_result read_file_splat(file_handle_t handle, void *buffer, uint64
|
|||
void wait_for_mouse_packet(struct mouse_packet *packet_out);
|
||||
|
||||
void *map_pages(uint64_t count);
|
||||
|
||||
void sleep_ms(uint64_t ms_to_sleep);
|
||||
|
|
|
|||
|
|
@ -25,5 +25,6 @@ enum {
|
|||
SYSCALL_GET_FILE_SIZE,
|
||||
SYSCALL_READ_FILE,
|
||||
SYSCALL_WAIT_FOR_MOUSE_PACKET,
|
||||
SYSCALL_MAP_PAGES
|
||||
SYSCALL_MAP_PAGES,
|
||||
SYSCALL_SLEEP_MS
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "paging.h"
|
||||
#include "input.h"
|
||||
#include "panic.h"
|
||||
#include "timer.h"
|
||||
#include "heap.h"
|
||||
#include "pata.h"
|
||||
#include "ps2.h"
|
||||
|
|
@ -243,9 +244,13 @@ static const char *cmdline_look_up(const char *key) {
|
|||
|
||||
//set up interrupts
|
||||
|
||||
init_timer();
|
||||
init_ps2();
|
||||
|
||||
set_irq_handler(0x00, &on_pit_irq);
|
||||
set_irq_handler(0x01, &on_keyboard_irq);
|
||||
set_irq_handler(0x0c, &on_mouse_irq);
|
||||
|
||||
enable_interrupts();
|
||||
|
||||
//set up syscalls
|
||||
|
|
@ -259,6 +264,7 @@ static const char *cmdline_look_up(const char *key) {
|
|||
register_syscall(SYSCALL_READ_FILE, (void *)&syscall_read_file);
|
||||
register_syscall(SYSCALL_WAIT_FOR_MOUSE_PACKET, (void *)&syscall_wait_for_mouse_packet);
|
||||
register_syscall(SYSCALL_MAP_PAGES, (void *)&syscall_map_pages);
|
||||
register_syscall(SYSCALL_SLEEP_MS, (void *)&syscall_sleep_ms);
|
||||
|
||||
//probe for drives
|
||||
|
||||
|
|
|
|||
37
src/kernel/timer.asm
Normal file
37
src/kernel/timer.asm
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
; Calcite, src/kernel/timer.asm
|
||||
; Copyright 2025 Benji Dial
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful, but
|
||||
; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
; for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License along
|
||||
; with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
bits 64
|
||||
default rel
|
||||
|
||||
section .text
|
||||
|
||||
global init_timer
|
||||
init_timer:
|
||||
|
||||
;generate an irq every 1193 cycles (~ every millisecond)
|
||||
|
||||
mov al, 0x34
|
||||
out 0x43, al
|
||||
|
||||
mov al, 0xa9
|
||||
out 0x40, al
|
||||
|
||||
mov al, 0x04
|
||||
out 0x40, al
|
||||
|
||||
ret
|
||||
93
src/kernel/timer.c
Normal file
93
src/kernel/timer.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* Calcite, src/kernel/timer.c
|
||||
* Copyright 2025 Benji Dial
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "timer.h"
|
||||
#include "heap.h"
|
||||
|
||||
struct sleeping_list_entry {
|
||||
struct sleeping_list_entry *next;
|
||||
uint64_t sleeping_until;//pit irqs since boot
|
||||
struct continuation_info continuation;
|
||||
};
|
||||
|
||||
//entries are always sorted increasing by sleeping_until
|
||||
static struct sleeping_list_entry *first_entry = 0;
|
||||
static struct sleeping_list_entry *last_entry = 0;
|
||||
|
||||
//pit irq happens ~ once per millisecond
|
||||
static uint64_t pit_irqs_since_boot = 0;
|
||||
|
||||
void on_pit_irq() {
|
||||
|
||||
++pit_irqs_since_boot;
|
||||
|
||||
while (first_entry != 0 && pit_irqs_since_boot >= first_entry->sleeping_until) {
|
||||
|
||||
add_to_queue(&ready_continuations, &first_entry->continuation);
|
||||
|
||||
struct sleeping_list_entry *old_first = first_entry;
|
||||
first_entry = old_first->next;
|
||||
heap_dealloc(old_first, sizeof(struct sleeping_list_entry));
|
||||
|
||||
if (first_entry == 0)
|
||||
last_entry = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//until in pit irqs since boot
|
||||
static void sleep_until(uint64_t until) {
|
||||
|
||||
struct sleeping_list_entry *entry = heap_alloc(sizeof(struct sleeping_list_entry));
|
||||
entry->sleeping_until = until;
|
||||
|
||||
__asm__ ("cli");
|
||||
|
||||
if (first_entry == 0) {
|
||||
entry->next = 0;
|
||||
first_entry = entry;
|
||||
last_entry = entry;
|
||||
}
|
||||
|
||||
else if (first_entry->sleeping_until >= until) {
|
||||
entry->next = first_entry;
|
||||
first_entry = entry;
|
||||
}
|
||||
|
||||
else if (last_entry->sleeping_until <= until) {
|
||||
entry->next = 0;
|
||||
last_entry->next = entry;
|
||||
last_entry = entry;
|
||||
}
|
||||
|
||||
else {
|
||||
struct sleeping_list_entry *just_before = first_entry;
|
||||
while (just_before->next->sleeping_until <= until)
|
||||
just_before = just_before->next;
|
||||
entry->next = just_before->next;
|
||||
just_before->next = entry;
|
||||
}
|
||||
|
||||
yield_sti(&entry->continuation);
|
||||
|
||||
}
|
||||
|
||||
void syscall_sleep_ms(uint64_t ms_to_sleep) {
|
||||
sleep_until(pit_irqs_since_boot + ms_to_sleep);
|
||||
}
|
||||
26
src/kernel/timer.h
Normal file
26
src/kernel/timer.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* Calcite, src/kernel/timer.h
|
||||
* Copyright 2025 Benji Dial
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void init_timer();
|
||||
|
||||
void on_pit_irq();
|
||||
|
||||
void syscall_sleep_ms(uint64_t ms_to_sleep);
|
||||
|
|
@ -76,6 +76,8 @@ void main() {
|
|||
|
||||
while (1) {
|
||||
|
||||
sleep_ms(10);
|
||||
|
||||
struct mouse_packet packet;
|
||||
wait_for_mouse_packet(&packet);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,3 +60,7 @@ void wait_for_mouse_packet(struct mouse_packet *packet_out) {
|
|||
void *map_pages(uint64_t count) {
|
||||
return (void *)do_syscall(count, 0, 0, SYSCALL_MAP_PAGES);
|
||||
}
|
||||
|
||||
void sleep_ms(uint64_t ms_to_sleep) {
|
||||
do_syscall(ms_to_sleep, 0, 0, SYSCALL_SLEEP_MS);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue