initial commit
This commit is contained in:
59
lib/kernel/io/IoMap.zig
Normal file
59
lib/kernel/io/IoMap.zig
Normal file
@@ -0,0 +1,59 @@
|
||||
pub fn IoMap(comptime T: type) type {
|
||||
return struct {
|
||||
pub const Permission = enum {
|
||||
readonly,
|
||||
writeonly,
|
||||
all,
|
||||
};
|
||||
|
||||
pub const Error = error {
|
||||
NotAvailable,
|
||||
};
|
||||
|
||||
pub const Pin = struct {
|
||||
kind: type = T,
|
||||
perm: Permission,
|
||||
base: usize,
|
||||
};
|
||||
|
||||
pub fn Schematics(comptime U: type) type {
|
||||
return struct {
|
||||
impl: T,
|
||||
init: bool = false,
|
||||
|
||||
pub fn open(self: *@This(), address: anytype) void {
|
||||
self.impl = T.open(address);
|
||||
self.init = true;
|
||||
}
|
||||
|
||||
pub fn read(self: *@This(), comptime name: []const u8) Error!@field(U{}, name).kind {
|
||||
if (@field(U{}, name).perm == .writeonly) {
|
||||
@compileError("attempted to perform a read operation on an unreadable field '" ++ name ++ "'");
|
||||
}
|
||||
if (self.init == false) {
|
||||
return error.NotAvailable;
|
||||
}
|
||||
const offset = @field(U{}, name).base;
|
||||
const address = self.impl.address + offset;
|
||||
|
||||
var io = T.open(@intCast(address));
|
||||
return io.read();
|
||||
}
|
||||
|
||||
pub fn write(self: *@This(), comptime name: []const u8, value: @field(U{}, name).kind) Error!void {
|
||||
if (@field(U{}, name).perm == .readonly) {
|
||||
@compileError("attempted to peform a write operation on an unwritable field '" ++ name ++ "'");
|
||||
}
|
||||
if (self.init == false) {
|
||||
return error.NotAvailable;
|
||||
}
|
||||
const offset = @field(U{}, name).base;
|
||||
const address = self.impl.address + offset;
|
||||
|
||||
var io = T.open(@intCast(address));
|
||||
io.write(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
47
lib/kernel/io/io.zig
Normal file
47
lib/kernel/io/io.zig
Normal file
@@ -0,0 +1,47 @@
|
||||
pub const IoMap = @import("IoMap.zig").IoMap;
|
||||
|
||||
pub fn Mmio(comptime T: type) type {
|
||||
return struct {
|
||||
address: usize,
|
||||
|
||||
pub fn open(address: usize) @This() {
|
||||
return .{ .address = address };
|
||||
}
|
||||
|
||||
pub fn read(self: *@This()) T {
|
||||
return @as(*T, @ptrFromInt(self.address)).*;
|
||||
}
|
||||
|
||||
pub fn write(self: *@This(), data: T) void {
|
||||
@as(*T, @ptrFromInt(self.address)).* = data;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn ReadOnly(comptime T: type) type {
|
||||
return struct {
|
||||
inner: T,
|
||||
|
||||
pub inline fn open(address: anytype) @This() {
|
||||
return .{ .inner = .open(address) };
|
||||
}
|
||||
|
||||
pub inline fn read(self: *@This()) void {
|
||||
return self.inner.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn WriteOnly(comptime T: type) type {
|
||||
return struct {
|
||||
inner: T,
|
||||
|
||||
pub inline fn open(address: anytype) @This() {
|
||||
return .{ .inner = .open(address) };
|
||||
}
|
||||
|
||||
pub inline fn write(self: *@This(), value: anytype) void {
|
||||
self.inner.write(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
5
lib/kernel/kernel.zig
Normal file
5
lib/kernel/kernel.zig
Normal file
@@ -0,0 +1,5 @@
|
||||
pub const io = @import("io/io.zig");
|
||||
pub const utils = @import("utils/utils.zig");
|
||||
pub const object = @import("object.zig");
|
||||
pub const machine = @import("machine/machine.zig");
|
||||
pub const syscall = @import("syscall.zig");
|
||||
1
lib/kernel/machine/machine.zig
Normal file
1
lib/kernel/machine/machine.zig
Normal file
@@ -0,0 +1 @@
|
||||
pub const serial = @import("serial/serial.zig");
|
||||
104
lib/kernel/machine/serial/16550.zig
Executable file
104
lib/kernel/machine/serial/16550.zig
Executable file
@@ -0,0 +1,104 @@
|
||||
const std = @import("std");
|
||||
const libk = @import("../../kernel.zig");
|
||||
|
||||
const IoMap = libk.io.IoMap;
|
||||
const BitFields = libk.utils.BitFields;
|
||||
|
||||
const IntEnFlags = BitFields(packed struct(u4) {
|
||||
received : bool = false,
|
||||
sent : bool = false,
|
||||
errored : bool = false,
|
||||
status_change : bool = false,
|
||||
});
|
||||
|
||||
const LineStsFlags = BitFields(packed struct(u8) {
|
||||
input_full : bool = false,
|
||||
padding_0 : u4 = 0,
|
||||
output_empty : bool = false,
|
||||
padding_1 : u2 = 0,
|
||||
});
|
||||
|
||||
pub fn SerialPort(comptime Io: type) type {
|
||||
return struct {
|
||||
io: IoMap(Io).Schematics(struct {
|
||||
/// Data port
|
||||
data : IoMap(u8).Pin = .{ .perm = .all, .base = 0 },
|
||||
/// Interrupt enable port
|
||||
int_en : IoMap(u8).Pin = .{ .perm = .writeonly, .base = 1 },
|
||||
/// Fifo control port
|
||||
fifo_ctrl : IoMap(u8).Pin = .{ .perm = .writeonly, .base = 2 },
|
||||
/// Line control port
|
||||
line_ctrl : IoMap(u8).Pin = .{ .perm = .writeonly, .base = 3 },
|
||||
/// Modem control port
|
||||
modem_ctrl : IoMap(u8).Pin = .{ .perm = .writeonly, .base = 4 },
|
||||
/// Line status port
|
||||
line_sts : IoMap(u8).Pin = .{ .perm = .readonly, .base = 5 },
|
||||
}),
|
||||
|
||||
pub fn open(self: *@This(), address: anytype) void {
|
||||
self.io.open(address);
|
||||
}
|
||||
|
||||
pub fn init(self: *@This()) !void {
|
||||
// Disable interrupts
|
||||
try self.io.write("int_en", IntEnFlags.init(.{}).bits());
|
||||
|
||||
// Enable DLAB
|
||||
try self.io.write("line_ctrl", 0x80);
|
||||
|
||||
// Set maximum speed to 38400 bps by configuring DLL and DLM
|
||||
try self.io.write("data", 0x03);
|
||||
try self.io.write("int_en", IntEnFlags.init(.{}).bits());
|
||||
|
||||
// Disable DLAB and set data word length to 8 bits
|
||||
try self.io.write("line_ctrl", 0x03);
|
||||
|
||||
// Enable FIFO, clear TX/RX queues and
|
||||
// set interrupt watermark at 14 bytes
|
||||
try self.io.write("fifo_ctrl", 0xC7);
|
||||
|
||||
// Mark data terminal ready, signal request to send
|
||||
// and enable auxilliary output #2 (used as interrupt line for CPU)
|
||||
try self.io.write("modem_ctrl", 0x0B);
|
||||
|
||||
// Enable interrupts
|
||||
try self.io.write("int_en", IntEnFlags.init(.{ .received = true }).bits());
|
||||
}
|
||||
|
||||
pub fn write(self: *@This(), data: []const u8) void {
|
||||
for (data) |byte| {
|
||||
switch (byte) {
|
||||
8, 0x7f => {
|
||||
self.send( 8 ) catch return;
|
||||
self.send(' ') catch return;
|
||||
self.send( 8 ) catch return;
|
||||
},
|
||||
else => {
|
||||
self.send(byte) catch return;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(self: *@This(), data: u8) !void {
|
||||
while (!(try self.lineSts()).fields.output_empty) {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
try self.io.write("data", data);
|
||||
}
|
||||
|
||||
pub fn receive(self: *@This()) !u8 {
|
||||
while (!(try self.lineSts()).fields.input_full) {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
return try self.io.read("data");
|
||||
}
|
||||
|
||||
inline fn lineSts(self: *@This()) !LineStsFlags {
|
||||
const data = try self.io.read("line_sts");
|
||||
const result = LineStsFlags.fromBitsTruncate(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
168
lib/kernel/machine/serial/pl011.zig
Executable file
168
lib/kernel/machine/serial/pl011.zig
Executable file
@@ -0,0 +1,168 @@
|
||||
const std = @import("std");
|
||||
const libk = @import("../../kernel.zig");
|
||||
|
||||
const Mmio = libk.io.Mmio;
|
||||
const IoMap = libk.io.IoMap;
|
||||
const BitFields = libk.utils.BitFields;
|
||||
|
||||
const Flags = BitFields(packed struct(u9) {
|
||||
/// Clear to send
|
||||
cts : bool = false,
|
||||
/// Data set ready
|
||||
dsr : bool = false,
|
||||
/// UART busy transmitting data
|
||||
dcd : bool = false,
|
||||
/// Receive FIFO is empty
|
||||
busy : bool = false,
|
||||
/// Transmit FIFO is empty
|
||||
rxfe : bool = false,
|
||||
/// Trasnmit FIFO is full
|
||||
txff : bool = false,
|
||||
/// Receive FIFO is full
|
||||
rxff : bool = false,
|
||||
/// Transmit FIFO is empty
|
||||
txfe : bool = false,
|
||||
/// Ring indicator
|
||||
ri : bool = false,
|
||||
});
|
||||
|
||||
const ReceiveStatus = BitFields(packed struct(u4) {
|
||||
/// Framing error
|
||||
fe: bool = false,
|
||||
/// Parity error
|
||||
pe: bool = false,
|
||||
/// Break error
|
||||
be: bool = false,
|
||||
/// Overrun error
|
||||
oe: bool = false,
|
||||
});
|
||||
|
||||
const Control = BitFields(packed struct(u16) {
|
||||
/// UART Enable
|
||||
uarten : bool = false,
|
||||
/// Serial InfraRed (SIR) Enable
|
||||
siren : bool = false,
|
||||
/// Serial InfraRed (SIR) Low-power
|
||||
sirlp : bool = false,
|
||||
/// Loopback Enable
|
||||
lbe : bool = false,
|
||||
/// Bits 6:3 reserved
|
||||
reserved : u4 = 0,
|
||||
/// Transmit Enable
|
||||
txe : bool = false,
|
||||
/// Receive Enable
|
||||
rxe : bool = false,
|
||||
/// Data Trasmit Ready
|
||||
dtr : bool = false,
|
||||
/// Request to Send
|
||||
rts : bool = false,
|
||||
/// Complement of nUARTOut1
|
||||
out_1 : bool = false,
|
||||
/// Complement of nUARTOut2
|
||||
out_2 : bool = false,
|
||||
/// Request To Send (RTS) Hardware Flow Control Enable
|
||||
rtsen : bool = false,
|
||||
/// Clear To Send (CTS) Hardware Flow Control Enable
|
||||
ctsen : bool = false,
|
||||
});
|
||||
|
||||
pub const SerialPort = struct {
|
||||
io: IoMap(Mmio(u32)).Schematics(struct {
|
||||
/// Data Register
|
||||
uartdr : IoMap(u32).Pin = .{ .perm = .all, .base = 0x00 },
|
||||
/// Receive status / error clear
|
||||
uartrsr : IoMap(u32).Pin = .{ .perm = .all, .base = 0x04 },
|
||||
/// Flag register
|
||||
uartfr : IoMap(u32).Pin = .{ .perm = .readonly, .base = 0x18 },
|
||||
/// IrDA Low power counter register
|
||||
uartilpr : IoMap(u32).Pin = .{ .perm = .all, .base = 0x20 },
|
||||
/// Integer baud rate
|
||||
uartibrd : IoMap(u32).Pin = .{ .perm = .all, .base = 0x24 },
|
||||
/// Fractional baud rate
|
||||
uartfbrd : IoMap(u32).Pin = .{ .perm = .all, .base = 0x28 },
|
||||
/// Line control
|
||||
uartlcr_h : IoMap(u32).Pin = .{ .perm = .all, .base = 0x2C },
|
||||
/// Control
|
||||
uartcr : IoMap(u32).Pin = .{ .perm = .all, .base = 0x30 },
|
||||
/// Interrupt fifo level select
|
||||
uartifls : IoMap(u32).Pin = .{ .perm = .all, .base = 0x34 },
|
||||
/// Interrupt mask set/clear
|
||||
uartimsc : IoMap(u32).Pin = .{ .perm = .all, .base = 0x38 },
|
||||
/// Raw interrupt status
|
||||
uartris : IoMap(u32).Pin = .{ .perm = .readonly, .base = 0x3C },
|
||||
/// Masked interrupt status
|
||||
uartmis : IoMap(u32).Pin = .{ .perm = .readonly, .base = 0x40 },
|
||||
/// Interrupt clear
|
||||
uarticr : IoMap(u32).Pin = .{ .perm = .writeonly, .base = 0x44 },
|
||||
/// Dma control
|
||||
uartdmacr : IoMap(u32).Pin = .{ .perm = .all, .base = 0x48 },
|
||||
}),
|
||||
|
||||
pub fn open(self: *@This(), address: usize) void {
|
||||
self.io.open(address);
|
||||
}
|
||||
|
||||
pub fn init(self: *@This(), clock: u32, baud_rate: u32) !void {
|
||||
const bits = try self.io.read("uartcr");
|
||||
var ctrl = Control.fromBitsTruncate(bits);
|
||||
|
||||
// Disable UART
|
||||
ctrl.fields.uarten = false;
|
||||
try self.io.write("uartcr", ctrl.bits());
|
||||
|
||||
// Program integer baud rate
|
||||
const divisor = (clock << 2) / baud_rate;
|
||||
try self.io.write("uartibrd", divisor >> 6);
|
||||
|
||||
// Program fractional baud rate
|
||||
try self.io.write("uartfbrd", divisor & 0x3F);
|
||||
|
||||
// Clear errors
|
||||
const status = ReceiveStatus.init(.{});
|
||||
try self.io.write("uartrsr", status.bits());
|
||||
|
||||
// Enable UART
|
||||
const data = Control.init(.{
|
||||
.rxe = true,
|
||||
.txe = true,
|
||||
.uarten = true,
|
||||
});
|
||||
try self.io.write("uartcr", data.bits());
|
||||
}
|
||||
|
||||
pub fn write(self: *@This(), data: []const u8) void {
|
||||
for (data) |byte| {
|
||||
switch (byte) {
|
||||
8, 0x7f => {
|
||||
self.send( 8 ) catch return;
|
||||
self.send(' ') catch return;
|
||||
self.send( 8 ) catch return;
|
||||
},
|
||||
else => {
|
||||
self.send(byte) catch return;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(self: *@This(), data: u32) !void {
|
||||
while ((try self.flags()).fields.txff) {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
try self.io.write("uartdr", data);
|
||||
}
|
||||
|
||||
pub fn receive(self: *@This()) !u32 {
|
||||
while ((try self.flags()).fields.rxff) {
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
return try self.io.read("uartdr");
|
||||
}
|
||||
|
||||
inline fn flags(self: *@This()) !Flags {
|
||||
const data = try self.io.read("uartfr");
|
||||
const result = Flags.fromBitsTruncate(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
2
lib/kernel/machine/serial/serial.zig
Normal file
2
lib/kernel/machine/serial/serial.zig
Normal file
@@ -0,0 +1,2 @@
|
||||
pub const uart_16550 = @import("16550.zig");
|
||||
pub const uart_pl011 = @import("pl011.zig");
|
||||
11
lib/kernel/object.zig
Normal file
11
lib/kernel/object.zig
Normal file
@@ -0,0 +1,11 @@
|
||||
pub const ObjectType = enum {
|
||||
untyped,
|
||||
endpoint,
|
||||
notification,
|
||||
cnode,
|
||||
tcb,
|
||||
schedctx,
|
||||
reply,
|
||||
interrupt,
|
||||
vspace,
|
||||
};
|
||||
0
lib/kernel/syscall.zig
Normal file
0
lib/kernel/syscall.zig
Normal file
30
lib/kernel/utils/BitFields.zig
Normal file
30
lib/kernel/utils/BitFields.zig
Normal file
@@ -0,0 +1,30 @@
|
||||
pub fn BitFields(comptime T: type) type {
|
||||
return packed struct {
|
||||
pub const Self = T;
|
||||
pub const Bits =
|
||||
if (@typeInfo(T).@"struct".backing_integer) |U| U
|
||||
else @compileError("T must be a packed struct");
|
||||
|
||||
fields: Self,
|
||||
|
||||
pub inline fn init(x: Self) @This() {
|
||||
return .{ .fields = x };
|
||||
}
|
||||
|
||||
pub inline fn fromBits(value: Bits) @This() {
|
||||
return .init(@bitCast(value));
|
||||
}
|
||||
|
||||
pub inline fn fromBitsTruncate(value: anytype) @This() {
|
||||
return fromBits(@truncate(value));
|
||||
}
|
||||
|
||||
pub inline fn bits(self: @This()) Bits {
|
||||
return @bitCast(self);
|
||||
}
|
||||
|
||||
pub inline fn cast(self: @This(), comptime Int: type) Int {
|
||||
return @intCast(bits(self));
|
||||
}
|
||||
};
|
||||
}
|
||||
12
lib/kernel/utils/utils.zig
Normal file
12
lib/kernel/utils/utils.zig
Normal file
@@ -0,0 +1,12 @@
|
||||
pub const BitFields = @import("BitFields.zig").BitFields;
|
||||
|
||||
pub inline fn alignDown(address: usize, alignment: usize) usize {
|
||||
return address & ~(alignment - 1);
|
||||
}
|
||||
|
||||
pub inline fn alignUp(address: usize, alignment: usize) usize {
|
||||
const mask = alignment - 1;
|
||||
if (address & mask == 0) return address;
|
||||
|
||||
return (address | mask) + 1;
|
||||
}
|
||||
10
lib/limine/limine.conf
Executable file
10
lib/limine/limine.conf
Executable file
@@ -0,0 +1,10 @@
|
||||
# Timeout in seconds that Limine will use before automatically booting.
|
||||
timeout: 0
|
||||
|
||||
# The entry name that will be displayed in the boot menu.
|
||||
/Tangerine
|
||||
# We use the Limine boot protocol.
|
||||
protocol: limine
|
||||
|
||||
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located.
|
||||
kernel_path: boot():/boot/kernel
|
||||
281
lib/limine/limine.zig
Executable file
281
lib/limine/limine.zig
Executable file
@@ -0,0 +1,281 @@
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn magic(a: u64, b: u64) [4]u64 {
|
||||
return .{ 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, a, b };
|
||||
}
|
||||
|
||||
pub const BaseRevision = extern struct {
|
||||
id: [2]u64 = .{ 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc },
|
||||
revision: u64,
|
||||
|
||||
pub fn is_supported(self: *const volatile @This()) bool {
|
||||
return self.revision == 0;
|
||||
}
|
||||
};
|
||||
|
||||
pub const BootloaderInfo = struct {
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0xf55038d8e2a1202f, 0x279426fcf5f59740),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
name: [*:0]u8,
|
||||
version: [*:0]u8,
|
||||
};
|
||||
};
|
||||
|
||||
pub const BootTime = struct {
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0x502746e184c088aa, 0xfbc5ec83e6327893),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
boot_time: i64,
|
||||
};
|
||||
};
|
||||
|
||||
pub const File = extern struct {
|
||||
revision: u64,
|
||||
address: [*]u8,
|
||||
size: u64,
|
||||
path: [*:0]u8,
|
||||
cmdline: [*:0]u8,
|
||||
media_type: MediaType,
|
||||
unused: u32,
|
||||
tftp_ip: u32,
|
||||
tftp_port: u32,
|
||||
partition_index: u32,
|
||||
mbr_disk_id: u32,
|
||||
gpt_disk_uuid: Uuid,
|
||||
gpt_part_uuid: Uuid,
|
||||
part_uuid: Uuid,
|
||||
|
||||
pub const Uuid = extern struct {
|
||||
a: u32,
|
||||
b: u16,
|
||||
c: u16,
|
||||
d: [8]u8,
|
||||
};
|
||||
|
||||
pub const MediaType = enum(u32) {
|
||||
generic = 0,
|
||||
optical = 1,
|
||||
tftp = 2,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Framebuffer = extern struct {
|
||||
address: [*]u8,
|
||||
width: u64,
|
||||
height: u64,
|
||||
pitch: u64,
|
||||
bpp: u16,
|
||||
memory_model: MemoryModel,
|
||||
red_mask_size: u8,
|
||||
red_mask_shift: u8,
|
||||
green_mask_size: u8,
|
||||
green_mask_shift: u8,
|
||||
blue_mask_size: u8,
|
||||
blue_mask_shift: u8,
|
||||
unused: [7]u8,
|
||||
edid_size: u64,
|
||||
edid: ?[*]u8,
|
||||
|
||||
// Response revision 1
|
||||
mode_count: u64,
|
||||
modes: [*]*VideoMode,
|
||||
|
||||
pub const MemoryModel = enum(u8) {
|
||||
rgb = 1,
|
||||
};
|
||||
|
||||
pub const VideoMode = extern struct {
|
||||
pitch: u64,
|
||||
width: u64,
|
||||
height: u64,
|
||||
bpp: u16,
|
||||
memory_model: MemoryModel,
|
||||
red_mask_size: u8,
|
||||
red_mask_shift: u8,
|
||||
green_mask_size: u8,
|
||||
green_mask_shift: u8,
|
||||
blue_mask_size: u8,
|
||||
blue_mask_shift: u8,
|
||||
};
|
||||
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0x9d5827dcd881dd75, 0xa3148604f6fab11b),
|
||||
revision: u64 = 1,
|
||||
response: ?*Response = null
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
framebuffer_count: u64,
|
||||
framebuffers: [*]*Framebuffer,
|
||||
|
||||
pub inline fn getFramebuffers(self: *@This()) []*Framebuffer {
|
||||
return self.framebuffers[0..self.framebuffer_count];
|
||||
}
|
||||
};
|
||||
|
||||
pub inline fn getEdid(self: *@This()) ?[]u8 {
|
||||
if (self.edid) |edid| {
|
||||
return edid[0..self.edid_size];
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn getModes(self: *@This()) []*VideoMode {
|
||||
return self.modes[0..self.mode_count];
|
||||
}
|
||||
};
|
||||
|
||||
pub const Hhdm = struct {
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0x48dcf1cb8ad2b852, 0x63984e959a98244b),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
offset: u64,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Rsdp = struct {
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0xc5e77b6b397e7b43, 0x27637845accdcf3c),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
address: u64,
|
||||
};
|
||||
};
|
||||
|
||||
pub const MemoryMap = struct {
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0x67cf3d9d378a806f, 0xe304acdfc50c3c62),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
entry_count: u64,
|
||||
entries: [*]*Entry,
|
||||
|
||||
pub inline fn getEntries(self: *@This()) []*Entry {
|
||||
return self.entries[0..self.entry_count];
|
||||
}
|
||||
};
|
||||
|
||||
pub const Entry = extern struct {
|
||||
base: u64,
|
||||
length: u64,
|
||||
type: EntryType,
|
||||
};
|
||||
|
||||
pub const EntryType = enum(u64) {
|
||||
usable = 0,
|
||||
reserved = 1,
|
||||
acpi_reclaimable = 2,
|
||||
acpi_nvs = 3,
|
||||
bad_memory = 4,
|
||||
bootloader_reclaimable = 5,
|
||||
kernel_and_modules = 6,
|
||||
framebuffer = 7,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Paging = struct {
|
||||
pub const Mode = switch (builtin.cpu.arch) {
|
||||
.aarch64, .x86_64 => enum(u64) {
|
||||
four_level,
|
||||
five_level,
|
||||
|
||||
pub inline fn default() Mode {
|
||||
return Mode.four_level;
|
||||
}
|
||||
|
||||
pub inline fn max() Mode {
|
||||
return Mode.five_level;
|
||||
}
|
||||
|
||||
pub inline fn min() Mode {
|
||||
return Mode.four_level;
|
||||
}
|
||||
},
|
||||
.loongarch64 => enum(u64) {
|
||||
four_level,
|
||||
|
||||
pub inline fn default() Mode {
|
||||
return Mode.four_level;
|
||||
}
|
||||
|
||||
pub inline fn max() Mode {
|
||||
return Mode.four_level;
|
||||
}
|
||||
|
||||
pub inline fn min() Mode {
|
||||
return Mode.four_level;
|
||||
}
|
||||
},
|
||||
.riscv64 => enum(u64) {
|
||||
sv39,
|
||||
sv48,
|
||||
sv57,
|
||||
|
||||
pub inline fn default() Mode {
|
||||
return Mode.sv48;
|
||||
}
|
||||
|
||||
pub inline fn max() Mode {
|
||||
return Mode.sv57;
|
||||
}
|
||||
|
||||
pub inline fn min() Mode {
|
||||
return Mode.sv39;
|
||||
}
|
||||
},
|
||||
else => |x| @compileError("Unsupported architecture: " ++ @tagName(x)),
|
||||
};
|
||||
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0x95c1a0edab0944cb, 0xa4e5cb3842f7488a),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
mode: Mode = .default(),
|
||||
|
||||
// Revision 1+
|
||||
max_mode: Mode = .max(),
|
||||
min_mode: Mode = .min(),
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
mode: Mode
|
||||
};
|
||||
};
|
||||
|
||||
pub const DeviceTreeBlob = struct {
|
||||
pub const Request = extern struct {
|
||||
id: [4]u64 = magic(0xb40ddb48fb54bac7, 0x545081493f81ffb7),
|
||||
revision: u64 = 0,
|
||||
response: ?*Response = null,
|
||||
};
|
||||
|
||||
pub const Response = extern struct {
|
||||
revision: u64,
|
||||
pointer: ?*anyopaque,
|
||||
};
|
||||
};
|
||||
75
lib/uacpi/uacpi.zig
Normal file
75
lib/uacpi/uacpi.zig
Normal file
@@ -0,0 +1,75 @@
|
||||
const C = @cImport({
|
||||
@cInclude("uacpi/event.h");
|
||||
@cInclude("uacpi/io.h");
|
||||
@cInclude("uacpi/namespace.h");
|
||||
@cInclude("uacpi/notify.h");
|
||||
@cInclude("uacpi/opregion.h");
|
||||
@cInclude("uacpi/osi.h");
|
||||
@cInclude("uacpi/resources.h");
|
||||
@cInclude("uacpi/sleep.h");
|
||||
@cInclude("uacpi/status.h");
|
||||
@cInclude("uacpi/tables.h");
|
||||
@cInclude("uacpi/types.h");
|
||||
@cInclude("uacpi/uacpi.h");
|
||||
@cInclude("uacpi/utilities.h");
|
||||
});
|
||||
|
||||
pub const Status = enum(C.uacpi_status) {
|
||||
ok = C.UACPI_STATUS_OK,
|
||||
mapping_failed = C.UACPI_STATUS_MAPPING_FAILED,
|
||||
out_of_memory = C.UACPI_STATUS_OUT_OF_MEMORY,
|
||||
bad_checksum = C.UACPI_STATUS_BAD_CHECKSUM,
|
||||
invalid_signature = C.UACPI_STATUS_INVALID_SIGNATURE,
|
||||
invalid_table_length = C.UACPI_STATUS_INVALID_TABLE_LENGTH,
|
||||
not_found = C.UACPI_STATUS_NOT_FOUND,
|
||||
invalid_argument = C.UACPI_STATUS_INVALID_ARGUMENT,
|
||||
unimplemented = C.UACPI_STATUS_UNIMPLEMENTED,
|
||||
already_exists = C.UACPI_STATUS_ALREADY_EXISTS,
|
||||
internal_error = C.UACPI_STATUS_INTERNAL_ERROR,
|
||||
type_mismatch = C.UACPI_STATUS_TYPE_MISMATCH,
|
||||
init_level_mismatch = C.UACPI_STATUS_INIT_LEVEL_MISMATCH,
|
||||
namespace_node_dangling = C.UACPI_STATUS_NAMESPACE_NODE_DANGLING,
|
||||
no_handler = C.UACPI_STATUS_NO_HANDLER,
|
||||
no_resource_end_tag = C.UACPI_STATUS_NO_RESOURCE_END_TAG,
|
||||
compiled_out = C.UACPI_STATUS_COMPILED_OUT,
|
||||
hardware_timeout = C.UACPI_STATUS_HARDWARE_TIMEOUT,
|
||||
timeout = C.UACPI_STATUS_TIMEOUT,
|
||||
overridden = C.UACPI_STATUS_OVERRIDDEN,
|
||||
denied = C.UACPI_STATUS_DENIED,
|
||||
|
||||
// All errors that have bytecode-related origin should go here
|
||||
aml_undefined_reference = C.UACPI_STATUS_AML_UNDEFINED_REFERENCE,
|
||||
aml_invalid_namestring = C.UACPI_STATUS_AML_INVALID_NAMESTRING,
|
||||
aml_object_already_exists = C.UACPI_STATUS_AML_OBJECT_ALREADY_EXISTS,
|
||||
aml_invalid_opcode = C.UACPI_STATUS_AML_INVALID_OPCODE,
|
||||
aml_incompatible_object_type = C.UACPI_STATUS_AML_INCOMPATIBLE_OBJECT_TYPE,
|
||||
aml_bad_encoding = C.UACPI_STATUS_AML_BAD_ENCODING,
|
||||
aml_out_of_bounds_index = C.UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX,
|
||||
aml_sync_level_too_high = C.UACPI_STATUS_AML_SYNC_LEVEL_TOO_HIGH,
|
||||
aml_invalid_resource = C.UACPI_STATUS_AML_INVALID_RESOURCE,
|
||||
aml_loop_timeout = C.UACPI_STATUS_AML_LOOP_TIMEOUT,
|
||||
aml_call_stack_depth_limit = C.UACPI_STATUS_AML_CALL_STACK_DEPTH_LIMIT,
|
||||
};
|
||||
|
||||
pub const InterruptResult = enum(C.uacpi_interrupt_ret) {
|
||||
not_handled = C.UACPI_INTERRUPT_NOT_HANDLED,
|
||||
handled = C.UACPI_INTERRUPT_HANDLED,
|
||||
};
|
||||
|
||||
pub const LogLevel = enum(C.uacpi_log_level) {
|
||||
debug = C.UACPI_LOG_DEBUG,
|
||||
err = C.UACPI_LOG_ERROR,
|
||||
info = C.UACPI_LOG_INFO,
|
||||
trace = C.UACPI_LOG_TRACE,
|
||||
warn = C.UACPI_LOG_WARN,
|
||||
};
|
||||
|
||||
pub const InterruptHandler = *const fn(Handle) callconv(.C) InterruptResult;
|
||||
|
||||
pub const Handle = C.uacpi_handle;
|
||||
pub const CpuFlags = C.uacpi_cpu_flags;
|
||||
pub const PhysAddr = C.uacpi_phys_addr;
|
||||
pub const ThreadId = C.uacpi_thread_id;
|
||||
pub const WorkType = C.uacpi_work_type;
|
||||
pub const PciAddress = C.uacpi_pci_address;
|
||||
pub const WorkHandler = C.uacpi_work_handler;
|
||||
Reference in New Issue
Block a user