204 lines
No EOL
7 KiB
Rust
204 lines
No EOL
7 KiB
Rust
use crate::arch::{stall, syscall};
|
|
use crate::TaskSetup;
|
|
|
|
#[repr(C)]
|
|
pub struct KernelInfo {
|
|
pub current_process_count: usize,
|
|
pub total_mem_blocks: usize,
|
|
pub free_mem_blocks: usize,
|
|
}
|
|
|
|
#[repr(u16)]
|
|
pub enum KTaskNotificationRequest {
|
|
DoNothing = 0,
|
|
SayHi = 1,
|
|
}
|
|
|
|
#[repr(u32)]
|
|
pub enum SysCall {
|
|
/// does absolutely nothing
|
|
NoAction = 0,
|
|
/// provide pointer to kernel info struct in first arg and it will be filled
|
|
KernelInfo = 1,
|
|
/// provide TaskSetup pointer in first arg and task will spawn, returns new task id
|
|
CreateTask = 2,
|
|
/// the currently executing task will exit
|
|
ExitTask = 3,
|
|
/// returns the current task id
|
|
CurrentTask = 4,
|
|
/// takes all available characters in the INBUF, places them in the given buffer, and returns the number of characters placed in the buffer
|
|
ReadInbuf = 5,
|
|
/// writes the given N characters in the buffer to the serial port
|
|
WriteTerminal = 6,
|
|
/// allocates N blocks of contiguous memory and returns the first block
|
|
AllocBlocks = 7,
|
|
/// frees N blocks starting at the given block
|
|
FreeBlocks = 8,
|
|
/// reads N sectors from the hard block device and writes them to the given block, this syscall will block the current task
|
|
/// returns 0 on success and 1 on failure
|
|
ReadHBD = 9,
|
|
/// sends a notification to the given task.
|
|
/// (taskid, addr) -> ret
|
|
/// returns 0 on success and 1 on failure (i.e. taskid is invalid)
|
|
/// addr is one block of memory.
|
|
/// calling this syscall will NOT block the current process, you must call WaitForNotification to
|
|
/// receive your reply.
|
|
/// the point at which you are allowed to free the block is dependent on the task that is waiting for the notification,
|
|
/// however in general it is not safe to free the block until a WaitForNotifAck is called.
|
|
/// IMPORTANT NOTE:
|
|
/// sending multiple notifications to a single task without calling WaitForNotifAck is NOT SUPPORTED
|
|
/// doing this results in undefined behavior
|
|
SendNotification = 10,
|
|
/// waits for a notification to arrive
|
|
/// () -> addr
|
|
/// this will block indefinitely until a notification arrives,^
|
|
/// use PendingNotifications to check if there are any pending notifications if you want to avoid blocking.
|
|
/// return value is an address to one block of memory.
|
|
/// this return value should also be used as a method of identified associated notifications,
|
|
/// i.e. in a system like the following
|
|
/// TASK1 - - - TASK2 - - - TASK1
|
|
/// send recv,send recv
|
|
/// the same block should be used for all notifications, and overwritten repeatedly
|
|
WaitForNotification = 11,
|
|
/// returns number of pending notifications
|
|
PendingNotifications = 12,
|
|
/// waits for a sent notification to be received
|
|
/// (taskid) -> 0
|
|
WaitForNotifAck = 13,
|
|
/// returns the environment pointer for the given task
|
|
EnvironmentPointer = 14,
|
|
/// disables the kernel framebuffer console, allowing you to use it for other purposes.
|
|
/// if there is no device providing a gpu, this will not do anything.
|
|
DisableFramebufferConsole = 15,
|
|
/// enables the kernel framebuffer console, this will result in an immediate framebuffer console reset.
|
|
/// if the framebuffer console is already enabled, then it will be reset upon calling this.
|
|
/// if there is no device providing a gpu, this will not do anything.
|
|
EnableFramebufferConsole = 16,
|
|
/// gets a pointer to the framebuffer
|
|
/// if there is no device providing a gpu, this will return a null pointer
|
|
FramebufferPointer = 17,
|
|
/// flushes changes done within the given rectangle to the framebuffer
|
|
/// if there is no device providing a gpu, this will not do anything
|
|
FlushFramebufferRect = 18,
|
|
|
|
/// initializes kernel, ONLY CALL ONCE! IN FACT, YOU PROBABLY NEVER NEED TO CALL THIS
|
|
InitKernel = 666
|
|
}
|
|
|
|
pub fn sc2usize(sc: SysCall) -> usize {
|
|
sc as usize
|
|
}
|
|
|
|
pub fn usize2sc(u: usize) -> SysCall {
|
|
match u {
|
|
0 => SysCall::NoAction,
|
|
1 => SysCall::KernelInfo,
|
|
2 => SysCall::CreateTask,
|
|
3 => SysCall::ExitTask,
|
|
4 => SysCall::CurrentTask,
|
|
5 => SysCall::ReadInbuf,
|
|
6 => SysCall::WriteTerminal,
|
|
7 => SysCall::AllocBlocks,
|
|
8 => SysCall::FreeBlocks,
|
|
9 => SysCall::ReadHBD,
|
|
10 => SysCall::SendNotification,
|
|
11 => SysCall::WaitForNotification,
|
|
12 => SysCall::PendingNotifications,
|
|
13 => SysCall::WaitForNotifAck,
|
|
14 => SysCall::EnvironmentPointer,
|
|
15 => SysCall::DisableFramebufferConsole,
|
|
16 => SysCall::EnableFramebufferConsole,
|
|
17 => SysCall::FramebufferPointer,
|
|
18 => SysCall::FlushFramebufferRect,
|
|
666 => SysCall::InitKernel,
|
|
_ => SysCall::NoAction,
|
|
}
|
|
}
|
|
|
|
pub fn kinfo() -> KernelInfo {
|
|
let mut kinfo = KernelInfo {
|
|
current_process_count: 0,
|
|
total_mem_blocks: 0,
|
|
free_mem_blocks: 0,
|
|
};
|
|
|
|
syscall(SysCall::KernelInfo, &mut kinfo as *mut KernelInfo as usize, 0, 0, 0, 0, 0);
|
|
|
|
kinfo
|
|
}
|
|
|
|
pub fn create_task(ts: TaskSetup) -> u8 {
|
|
syscall(SysCall::CreateTask, &ts as *const TaskSetup as usize, 0, 0, 0, 0, 0) as u8
|
|
}
|
|
|
|
pub fn exit() -> ! {
|
|
syscall(SysCall::ExitTask, 0, 0, 0, 0, 0, 0);
|
|
|
|
loop {
|
|
stall();
|
|
}
|
|
}
|
|
|
|
pub fn current_task() -> u8 {
|
|
syscall(SysCall::CurrentTask, 0, 0, 0, 0, 0, 0) as u8
|
|
}
|
|
|
|
pub fn read_inbuf(buf: &mut [u8]) -> usize {
|
|
syscall(SysCall::ReadInbuf, buf.as_mut_ptr() as usize, buf.len(), 0, 0, 0, 0)
|
|
}
|
|
|
|
pub fn alloc_blocks(n: usize) -> usize {
|
|
syscall(SysCall::AllocBlocks, n, 0, 0, 0, 0, 0)
|
|
}
|
|
|
|
pub fn free_blocks(addr: usize, n: usize) {
|
|
syscall(SysCall::FreeBlocks, addr, n, 0, 0, 0, 0);
|
|
}
|
|
|
|
pub fn write_terminal(buf: &[u8]) {
|
|
syscall(SysCall::WriteTerminal, buf.as_ptr() as usize, buf.len(), 0, 0, 0, 0);
|
|
}
|
|
|
|
pub fn read_hbd(sector: usize, buf_addr: usize, count: usize) -> usize {
|
|
syscall(SysCall::ReadHBD, sector, buf_addr, count, 0, 0, 0)
|
|
}
|
|
|
|
pub fn send_notification(taskid: u8, addr: usize) {
|
|
syscall(SysCall::SendNotification, taskid as usize, addr, 0, 0, 0, 0);
|
|
}
|
|
|
|
pub fn wait_for_notification() -> usize {
|
|
syscall(SysCall::WaitForNotification, 0, 0, 0, 0, 0, 0)
|
|
}
|
|
|
|
pub fn pending_notifications() -> usize {
|
|
syscall(SysCall::PendingNotifications, 0, 0, 0, 0, 0, 0)
|
|
}
|
|
|
|
pub fn wait_for_notif_ack(taskid: u8) {
|
|
syscall(SysCall::WaitForNotifAck, taskid as usize, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
pub fn environment_pointer() -> usize {
|
|
syscall(SysCall::EnvironmentPointer, 0, 0, 0, 0, 0, 0)
|
|
}
|
|
|
|
pub fn disable_framebuffer_console() {
|
|
syscall(SysCall::DisableFramebufferConsole, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
pub fn enable_framebuffer_console() {
|
|
syscall(SysCall::EnableFramebufferConsole, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
pub fn framebuffer_pointer() -> usize {
|
|
syscall(SysCall::FramebufferPointer, 0, 0, 0, 0, 0, 0)
|
|
}
|
|
|
|
pub fn flush_framebuffer_rect(x: usize, y: usize, w: usize, h: usize) {
|
|
syscall(SysCall::FlushFramebufferRect, x, y, w, h, 0, 0);
|
|
}
|
|
|
|
pub fn init_kernel() {
|
|
syscall(SysCall::InitKernel, 0, 0, 0, 0, 0, 0);
|
|
} |