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