zig/std/os/zen.zig

261 lines
6.5 KiB
Zig
Raw Normal View History

2018-04-13 13:24:57 +08:00
const std = @import("../index.zig");
const assert = std.debug.assert;
2018-03-20 23:40:33 +08:00
//////////////////////////
//// IPC structures ////
//////////////////////////
2018-03-15 13:07:17 +08:00
pub const Message = struct {
2018-08-28 07:25:18 +08:00
sender: MailboxId,
2018-03-15 17:22:03 +08:00
receiver: MailboxId,
2018-08-28 07:25:18 +08:00
code: usize,
args: [5]usize,
payload: ?[]const u8,
2018-03-15 13:07:17 +08:00
pub fn from(mailbox_id: *const MailboxId) Message {
return Message{
2018-08-28 07:25:18 +08:00
.sender = MailboxId.Undefined,
2018-08-06 13:43:19 +08:00
.receiver = mailbox_id.*,
2018-08-28 07:25:18 +08:00
.code = undefined,
.args = undefined,
.payload = null,
2018-03-15 13:07:17 +08:00
};
}
2018-08-06 13:43:19 +08:00
pub fn to(mailbox_id: *const MailboxId, msg_code: usize, args: ...) Message {
var message = Message{
2018-08-28 07:25:18 +08:00
.sender = MailboxId.This,
2018-08-06 13:43:19 +08:00
.receiver = mailbox_id.*,
2018-08-28 07:25:18 +08:00
.code = msg_code,
.args = undefined,
.payload = null,
};
2018-04-13 13:24:57 +08:00
2018-08-28 07:25:18 +08:00
assert(args.len <= message.args.len);
2018-04-13 13:24:57 +08:00
comptime var i = 0;
inline while (i < args.len) : (i += 1) {
message.args[i] = args[i];
}
return message;
}
2018-08-06 13:43:19 +08:00
pub fn as(self: *const Message, sender: *const MailboxId) Message {
var message = self.*;
message.sender = sender.*;
2018-04-11 15:31:32 +08:00
return message;
}
2018-08-06 13:43:19 +08:00
pub fn withPayload(self: *const Message, payload: []const u8) Message {
var message = self.*;
2018-04-13 13:24:57 +08:00
message.payload = payload;
2018-04-11 15:31:32 +08:00
return message;
}
2018-03-15 13:07:17 +08:00
};
pub const MailboxId = union(enum) {
Undefined,
2018-03-15 17:22:03 +08:00
This,
2018-03-15 13:07:17 +08:00
Kernel,
2018-05-29 08:23:55 +08:00
Port: u16,
2018-03-16 16:41:45 +08:00
Thread: u16,
2018-03-15 13:07:17 +08:00
};
2018-03-17 11:27:13 +08:00
//////////////////////////////////////
//// Ports reserved for servers ////
//////////////////////////////////////
2018-01-07 17:43:08 +08:00
pub const Server = struct {
pub const Keyboard = MailboxId{ .Port = 0 };
pub const Terminal = MailboxId{ .Port = 1 };
2018-03-15 17:22:03 +08:00
};
2018-01-07 17:43:08 +08:00
////////////////////////
//// POSIX things ////
////////////////////////
// Standard streams.
2018-05-29 08:23:55 +08:00
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;
// FIXME: let's borrow Linux's error numbers for now.
use @import("linux/errno.zig");
2018-08-06 14:42:12 +08:00
// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) usize {
const signed_r = @bitCast(isize, r);
return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
}
// TODO: implement this correctly.
2018-08-06 14:42:12 +08:00
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
switch (fd) {
STDIN_FILENO => {
var i: usize = 0;
while (i < count) : (i += 1) {
send(Message.to(Server.Keyboard, 0));
2018-04-14 02:10:36 +08:00
// FIXME: we should be certain that we are receiving from Keyboard.
var message = Message.from(MailboxId.This);
2018-08-06 14:42:12 +08:00
receive(&message);
2018-08-06 14:42:12 +08:00
buf[i] = @intCast(u8, message.args[0]);
}
},
else => unreachable,
}
return count;
}
// TODO: implement this correctly.
2018-08-06 14:42:12 +08:00
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
switch (fd) {
STDOUT_FILENO, STDERR_FILENO => {
2018-08-28 07:25:18 +08:00
send(Message.to(Server.Terminal, 1).withPayload(buf[0..count]));
},
else => unreachable,
}
return count;
}
2018-01-07 17:43:08 +08:00
///////////////////////////
//// Syscall numbers ////
///////////////////////////
pub const Syscall = enum(usize) {
2018-08-28 07:25:18 +08:00
exit = 0,
send = 1,
receive = 2,
subscribeIRQ = 3,
inb = 4,
outb = 5,
map = 6,
createThread = 7,
2018-03-15 17:22:03 +08:00
};
2018-01-07 17:43:08 +08:00
////////////////////
//// Syscalls ////
////////////////////
pub fn exit(status: i32) noreturn {
2018-03-15 17:22:03 +08:00
_ = syscall1(Syscall.exit, @bitCast(usize, isize(status)));
2018-01-09 01:16:23 +08:00
unreachable;
}
pub fn send(message: *const Message) void {
2018-03-15 17:22:03 +08:00
_ = syscall1(Syscall.send, @ptrToInt(message));
2018-01-07 17:43:08 +08:00
}
pub fn receive(destination: *Message) void {
2018-03-15 17:22:03 +08:00
_ = syscall1(Syscall.receive, @ptrToInt(destination));
2018-01-07 17:43:08 +08:00
}
pub fn subscribeIRQ(irq: u8, mailbox_id: *const MailboxId) void {
2018-03-15 19:28:05 +08:00
_ = syscall2(Syscall.subscribeIRQ, irq, @ptrToInt(mailbox_id));
}
pub fn inb(port: u16) u8 {
2018-08-06 14:29:11 +08:00
return @intCast(u8, syscall1(Syscall.inb, port));
2018-03-15 19:28:05 +08:00
}
2018-04-12 14:11:26 +08:00
pub fn outb(port: u16, value: u8) void {
_ = syscall2(Syscall.outb, port, value);
}
pub fn map(v_addr: usize, p_addr: usize, size: usize, writable: bool) bool {
2018-08-06 14:29:11 +08:00
return syscall4(Syscall.map, v_addr, p_addr, size, @boolToInt(writable)) != 0;
2018-01-07 17:43:08 +08:00
}
2018-05-31 04:09:11 +08:00
pub fn createThread(function: fn () void) u16 {
2018-03-15 17:22:03 +08:00
return u16(syscall1(Syscall.createThread, @ptrToInt(function)));
2018-01-09 01:16:23 +08:00
}
2018-01-07 17:43:08 +08:00
/////////////////////////
//// Syscall stubs ////
/////////////////////////
2018-03-15 19:28:05 +08:00
inline fn syscall0(number: Syscall) usize {
2018-01-07 17:43:08 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
2018-05-29 08:23:55 +08:00
: [number] "{eax}" (number)
);
2018-01-07 17:43:08 +08:00
}
2018-03-15 19:28:05 +08:00
inline fn syscall1(number: Syscall, arg1: usize) usize {
2018-01-07 17:43:08 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (number),
2018-05-29 08:23:55 +08:00
[arg1] "{ecx}" (arg1)
);
2018-01-07 17:43:08 +08:00
}
2018-03-15 19:28:05 +08:00
inline fn syscall2(number: Syscall, arg1: usize, arg2: usize) usize {
2018-01-07 17:43:08 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (number),
2018-05-29 08:23:55 +08:00
[arg1] "{ecx}" (arg1),
[arg2] "{edx}" (arg2)
);
2018-01-07 17:43:08 +08:00
}
2018-03-15 19:28:05 +08:00
inline fn syscall3(number: Syscall, arg1: usize, arg2: usize, arg3: usize) usize {
2018-01-07 17:43:08 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (number),
2018-05-29 08:23:55 +08:00
[arg1] "{ecx}" (arg1),
[arg2] "{edx}" (arg2),
[arg3] "{ebx}" (arg3)
);
2018-01-07 17:43:08 +08:00
}
2018-03-15 19:28:05 +08:00
inline fn syscall4(number: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
2018-01-07 17:43:08 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (number),
2018-05-29 08:23:55 +08:00
[arg1] "{ecx}" (arg1),
[arg2] "{edx}" (arg2),
[arg3] "{ebx}" (arg3),
[arg4] "{esi}" (arg4)
);
2018-01-07 17:43:08 +08:00
}
2018-05-29 08:23:55 +08:00
inline fn syscall5(
number: Syscall,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
arg5: usize,
) usize {
2018-01-07 17:43:08 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (number),
2018-05-29 08:23:55 +08:00
[arg1] "{ecx}" (arg1),
[arg2] "{edx}" (arg2),
[arg3] "{ebx}" (arg3),
[arg4] "{esi}" (arg4),
[arg5] "{edi}" (arg5)
);
2018-01-07 17:43:08 +08:00
}
2018-03-10 14:24:52 +08:00
2018-05-29 08:23:55 +08:00
inline fn syscall6(
number: Syscall,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
arg5: usize,
arg6: usize,
) usize {
2018-03-10 14:24:52 +08:00
return asm volatile ("int $0x80"
: [ret] "={eax}" (-> usize)
: [number] "{eax}" (number),
2018-05-29 08:23:55 +08:00
[arg1] "{ecx}" (arg1),
[arg2] "{edx}" (arg2),
[arg3] "{ebx}" (arg3),
[arg4] "{esi}" (arg4),
[arg5] "{edi}" (arg5),
[arg6] "{ebp}" (arg6)
);
2018-03-10 14:24:52 +08:00
}