added virtio, refactoring untill compiler is fixed
This commit is contained in:
parent
4c9f4b54d8
commit
d051e1b0c8
12 changed files with 112 additions and 163 deletions
|
|
@ -8,6 +8,15 @@ const gdt = @import("gdt.zig");
|
||||||
pub const INTERRUPT_GATE = 0x8E;
|
pub const INTERRUPT_GATE = 0x8E;
|
||||||
pub const SYSCALL_GATE = 0xEE;
|
pub const SYSCALL_GATE = 0xEE;
|
||||||
|
|
||||||
|
// Interrupt Descriptor Table.
|
||||||
|
var idt: [256]IDTEntry = undefined;
|
||||||
|
|
||||||
|
// IDT descriptor register pointing at the IDT.
|
||||||
|
const idtr = IDTRegister{
|
||||||
|
.limit = u16(@sizeOf(@typeOf(idt))),
|
||||||
|
.base = &idt,
|
||||||
|
};
|
||||||
|
|
||||||
// Structure representing an entry in the IDT.
|
// Structure representing an entry in the IDT.
|
||||||
const IDTEntry = packed struct {
|
const IDTEntry = packed struct {
|
||||||
offset_low: u16,
|
offset_low: u16,
|
||||||
|
|
@ -23,16 +32,6 @@ const IDTRegister = packed struct {
|
||||||
base: *[256]IDTEntry,
|
base: *[256]IDTEntry,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interrupt Descriptor Table.
|
|
||||||
var idt: [256]IDTEntry = undefined;
|
|
||||||
|
|
||||||
// IDT descriptor register pointing at the IDT.
|
|
||||||
const idtr = IDTRegister{
|
|
||||||
.limit = u16(@sizeOf(@typeOf(idt))),
|
|
||||||
.base = &idt,
|
|
||||||
};
|
|
||||||
|
|
||||||
////
|
|
||||||
// Setup an IDT entry.
|
// Setup an IDT entry.
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
|
@ -50,9 +49,7 @@ pub fn setGate(n: u8, flags: u8, offset: extern fn () void) void {
|
||||||
idt[n].selector = gdt.KERNEL_CODE;
|
idt[n].selector = gdt.KERNEL_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
|
||||||
// Initialize the Interrupt Descriptor Table.
|
// Initialize the Interrupt Descriptor Table.
|
||||||
//
|
|
||||||
pub fn initialize() void {
|
pub fn initialize() void {
|
||||||
// configure PIC and set ISRs
|
// configure PIC and set ISRs
|
||||||
interrupt.initialize();
|
interrupt.initialize();
|
||||||
|
|
|
||||||
|
|
@ -164,15 +164,13 @@ fn remapPIC() void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maskIRQ(irq: u8, mask: bool) void {
|
pub fn maskIRQ(irq: u8, mask: bool) void {
|
||||||
if (irq > 15) {
|
if (irq > 15) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Figure out if master or slave PIC owns the IRQ.
|
// Figure out if master or slave PIC owns the IRQ.
|
||||||
const port = if (irq < 8) u16(PIC1_DATA) else u16(PIC2_DATA);
|
const port = if (irq < 8) u16(PIC1_DATA) else u16(PIC2_DATA);
|
||||||
const old = x86.inb(port); // Retrieve the current mask.
|
const old = x86.inb(port); // Retrieve the current mask.
|
||||||
|
|
||||||
// Mask or unmask the interrupt.
|
// Mask or unmask the interrupt.
|
||||||
const shift = @intCast(u3, irq % 8); // TODO: waiting for Andy to fix this.
|
const shift = @intCast(u3, irq % 8);
|
||||||
if (mask) {
|
if (mask) {
|
||||||
x86.outb(port, old | (u8(1) << shift));
|
x86.outb(port, old | (u8(1) << shift));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -80,19 +80,6 @@ pub const Registers = packed struct {
|
||||||
edx: u32,
|
edx: u32,
|
||||||
ecx: u32,
|
ecx: u32,
|
||||||
eax: u32,
|
eax: u32,
|
||||||
|
|
||||||
pub fn init() Registers {
|
|
||||||
return Registers{
|
|
||||||
.edi = 0,
|
|
||||||
.esi = 0,
|
|
||||||
.ebp = 0,
|
|
||||||
.esp = 0,
|
|
||||||
.ebx = 0,
|
|
||||||
.edx = 0,
|
|
||||||
.ecx = 0,
|
|
||||||
.eax = 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pointer to the current saved context.
|
// Pointer to the current saved context.
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,7 @@ pub inline fn ltr(desc: u16) void {
|
||||||
//
|
//
|
||||||
pub inline fn hang() noreturn {
|
pub inline fn hang() noreturn {
|
||||||
asm volatile ("cli");
|
asm volatile ("cli");
|
||||||
while (true) {
|
while (true) asm volatile ("hlt");
|
||||||
asm volatile ("hlt");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn sti() void {
|
pub inline fn sti() void {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ pub fn allocate() ?usize {
|
||||||
println("out of memory");
|
println("out of memory");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_index -= 1;
|
stack_index -= 1;
|
||||||
return stack[stack_index];
|
return stack[stack_index];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,7 @@ pub var pageDirectory: [1024]PageEntry align(4096) linksection(".bss") = [_]Page
|
||||||
|
|
||||||
fn pageFault() void {
|
fn pageFault() void {
|
||||||
println("pagefault");
|
println("pagefault");
|
||||||
while (true) {
|
while (true) asm volatile ("hlt");
|
||||||
asm volatile ("hlt");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pageBase(addr: usize) usize {
|
fn pageBase(addr: usize) usize {
|
||||||
|
|
@ -44,21 +42,17 @@ pub fn translate(virt: usize) ?usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unmap(virt: usize) void {
|
pub fn unmap(virt: usize) void {
|
||||||
var pte = pte(virt);
|
if (translate(virt)) |phys| {
|
||||||
if (pte.* == 0) {
|
|
||||||
println("can't unmap 0x{x}, map is empty.", addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pte.* = 0;
|
|
||||||
memory.free(translate(virt));
|
memory.free(translate(virt));
|
||||||
|
} else {
|
||||||
|
println("can't unmap 0x{x}, map is empty.", addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mmap(virt: usize, phys: ?usize) void {
|
pub fn mmap(virt: usize, phys: ?usize) void {
|
||||||
var pde: *PageEntry = &PD[virt >> 22];
|
var pde: *PageEntry = pde(virt);
|
||||||
if (pde.* == 0) {
|
if (pde.* == 0) pde.* = memory.allocate() | WRITE | PRESENT;
|
||||||
pde.* = memory.allocate() | WRITE | PRESENT;
|
var pte: *PageEntry = pte(virt);
|
||||||
}
|
|
||||||
var pte: *PageEntry = &PT[virt >> 12];
|
|
||||||
pte.* = if (phys) |p| p else allocate() | PRESENT;
|
pte.* = if (phys) |p| p else allocate() | PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,35 +60,27 @@ pub fn addrspace() void {
|
||||||
var i: usize = 1;
|
var i: usize = 1;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < 1024) : (i += 1) {
|
while (i < 1024) : (i += 1) {
|
||||||
if (PD[i] == 0) {
|
if (PD[i] == 0) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
println("p2[{}] -> 0x{x}", i, PD[i]);
|
println("p2[{}] -> 0x{x}", i, PD[i]);
|
||||||
if (PD[i] & HUGE != 0) {
|
if (PD[i] & HUGE != 0) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var j: usize = 0;
|
var j: usize = 0;
|
||||||
while (j < 1024) : (j += 1) {
|
while (j < 1024) : (j += 1) {
|
||||||
var entry: PageEntry = PT[i * 1024 + j];
|
var entry: PageEntry = PT[i * 1024 + j];
|
||||||
if (entry != 0) {
|
if (entry != 0) println("p2[{}]p1[{}] -> 0x{x}", i, j, entry);
|
||||||
println("p2[{}]p1[{}] -> 0x{x}", i, j, entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize() void {
|
pub fn initialize() void {
|
||||||
var p2 = pageDirectory[0..];
|
var p2 = pageDirectory[0..];
|
||||||
// identity map 0 -> 4MB
|
|
||||||
|
|
||||||
|
// identity map 0 -> 4MB
|
||||||
p2[0] = 0x000000 | PRESENT | WRITE | HUGE;
|
p2[0] = 0x000000 | PRESENT | WRITE | HUGE;
|
||||||
|
// recursive mapping
|
||||||
p2[1023] = @ptrToInt(&p2[0]) | PRESENT | WRITE;
|
p2[1023] = @ptrToInt(&p2[0]) | PRESENT | WRITE;
|
||||||
|
|
||||||
assert(memory.stack_end < 0x400000);
|
assert(memory.stack_end < 0x400000);
|
||||||
// const first: *u32 = @ptrCast(*u32, p2);
|
|
||||||
// println("p2[0] {b}", first.*);
|
|
||||||
|
|
||||||
interrupt.register(14, pageFault);
|
interrupt.register(14, pageFault);
|
||||||
setupPaging(@ptrToInt(&pageDirectory[0]));
|
setupPaging(@ptrToInt(&pageDirectory[0]));
|
||||||
// const addr = mapper.translate(0xfffff000);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
const interrupt = @import("arch/x86/interrupt.zig");
|
const interrupt = @import("arch/x86/interrupt.zig");
|
||||||
const paging = @import("arch/x86/paging.zig");
|
const paging = @import("arch/x86/paging.zig");
|
||||||
const ps2 = @import("ps2.zig");
|
const ps2 = @import("ps2.zig");
|
||||||
// const pci = @import("pci.zig");
|
const pci = @import("pci.zig");
|
||||||
const mem = @import("std").mem;
|
const mem = @import("std").mem;
|
||||||
usingnamespace @import("vga.zig");
|
usingnamespace @import("vga.zig");
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ var command: [10]u8 = undefined;
|
||||||
var command_len: usize = 0;
|
var command_len: usize = 0;
|
||||||
|
|
||||||
fn execute(com: []u8) void {
|
fn execute(com: []u8) void {
|
||||||
// if (mem.eql(u8, com, "lspci")) pci.lspci();
|
if (mem.eql(u8, com, "lspci")) pci.lspci();
|
||||||
if (mem.eql(u8, com, "paging")) paging.addrspace();
|
if (mem.eql(u8, com, "paging")) paging.addrspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,21 +17,16 @@ pub fn keypress(char: u8) void {
|
||||||
// this is a custom "readline" capped at 10 characters
|
// this is a custom "readline" capped at 10 characters
|
||||||
switch (char) {
|
switch (char) {
|
||||||
'\n' => {
|
'\n' => {
|
||||||
vga.writeChar('\n');
|
print("\n");
|
||||||
execute(command[0..command_len]);
|
execute(command[0..command_len]);
|
||||||
vga.writeString("> ");
|
print("> ");
|
||||||
command_len = 0;
|
command_len = 0;
|
||||||
},
|
},
|
||||||
'\x08' => {
|
'\x08' => return, //backspace
|
||||||
//backspace
|
'\x00' => return,
|
||||||
return;
|
|
||||||
},
|
|
||||||
'\x00' => {
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
else => {
|
else => {
|
||||||
if (command_len == 10)
|
// general case
|
||||||
return;
|
if (command_len == 10) return;
|
||||||
vga.writeChar(char);
|
vga.writeChar(char);
|
||||||
command[command_len] = char;
|
command[command_len] = char;
|
||||||
command_len += 1;
|
command_len += 1;
|
||||||
|
|
|
||||||
10
src/main.zig
10
src/main.zig
|
|
@ -8,16 +8,14 @@ const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
// arch independant initialization
|
// arch independant initialization
|
||||||
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
export fn kmain(magic: u32, info: *const MultibootInfo) noreturn {
|
||||||
clear();
|
|
||||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
||||||
|
|
||||||
|
clear();
|
||||||
println("--- x86 initialization ---");
|
println("--- x86 initialization ---");
|
||||||
|
|
||||||
x86.x86_main(info);
|
x86.x86_main(info);
|
||||||
|
|
||||||
println("--- core initialization ---");
|
println("--- core initialization ---");
|
||||||
pci.scan();
|
pci.scan();
|
||||||
console.initialize();
|
console.initialize();
|
||||||
while (true) {
|
|
||||||
asm volatile ("hlt");
|
while (true) asm volatile ("hlt");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
78
src/pci.zig
78
src/pci.zig
|
|
@ -4,7 +4,9 @@ const PCI_CONFIG_ADDRESS = 0xCF8;
|
||||||
const PCI_CONFIG_DATA = 0xCFC;
|
const PCI_CONFIG_DATA = 0xCFC;
|
||||||
usingnamespace @import("vga.zig");
|
usingnamespace @import("vga.zig");
|
||||||
const virtio = @import("virtio.zig");
|
const virtio = @import("virtio.zig");
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
// https://wiki.osdev.org/Pci
|
||||||
pub const PciAddress = packed struct {
|
pub const PciAddress = packed struct {
|
||||||
offset: u8,
|
offset: u8,
|
||||||
function: u3,
|
function: u3,
|
||||||
|
|
@ -21,12 +23,8 @@ pub const PciDevice = struct {
|
||||||
vendor: u16 = undefined,
|
vendor: u16 = undefined,
|
||||||
|
|
||||||
pub fn init(bus: u8, slot: u5, function: u3) ?PciDevice {
|
pub fn init(bus: u8, slot: u5, function: u3) ?PciDevice {
|
||||||
var dev = PciDevice{
|
var dev = PciDevice{ .bus = bus, .slot = slot, .function = function };
|
||||||
.bus = bus,
|
dev.vendor = dev.config_read(u16, 0);
|
||||||
.slot = slot,
|
|
||||||
.function = function,
|
|
||||||
};
|
|
||||||
dev.vendor = dev.config_read_word(0);
|
|
||||||
if (dev.vendor == 0xffff) return null;
|
if (dev.vendor == 0xffff) return null;
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +43,8 @@ pub const PciDevice = struct {
|
||||||
|
|
||||||
pub fn format(self: PciDevice) void {
|
pub fn format(self: PciDevice) void {
|
||||||
print("{}:{}.{}", self.bus, self.slot, self.function);
|
print("{}:{}.{}", self.bus, self.slot, self.function);
|
||||||
print(" {x},{x:2}(0x{x:4}): 0x{x} 0x{x}", self.class(), self.subclass(), self.subsystem(), self.vendor, self.device());
|
print(" {x},{x:2}", self.class(), self.subclass());
|
||||||
|
print(" 0x{x},0x{x}", self.vendor, self.device());
|
||||||
if (self.driver()) |d|
|
if (self.driver()) |d|
|
||||||
print(" {}", d.name);
|
print(" {}", d.name);
|
||||||
println("");
|
println("");
|
||||||
|
|
@ -57,48 +56,44 @@ pub const PciDevice = struct {
|
||||||
var drv = Drivers[i];
|
var drv = Drivers[i];
|
||||||
if (self.class() != drv.class or self.subclass() != drv.subclass)
|
if (self.class() != drv.class or self.subclass() != drv.subclass)
|
||||||
continue;
|
continue;
|
||||||
if (drv.vendor) |v| if (self.vendor == v)
|
if (drv.vendor) |v| if (self.vendor != v)
|
||||||
continue;
|
continue;
|
||||||
if (drv.subsystem) |ss| if (self.subsystem() == drv.subsystem.?)
|
if (drv.subsystem) |ss| if (self.subsystem() != ss)
|
||||||
continue;
|
continue;
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all pci device must implement these
|
||||||
pub fn device(self: PciDevice) u16 {
|
pub fn device(self: PciDevice) u16 {
|
||||||
return self.config_read_word(2);
|
return self.config_read(u16, 0x2);
|
||||||
}
|
}
|
||||||
pub fn subclass(self: PciDevice) u16 {
|
pub fn subclass(self: PciDevice) u8 {
|
||||||
return self.config_read_byte(10);
|
return self.config_read(u8, 0xa);
|
||||||
}
|
}
|
||||||
pub fn class(self: PciDevice) u16 {
|
pub fn class(self: PciDevice) u8 {
|
||||||
return self.config_read_byte(11);
|
return self.config_read(u8, 0xb);
|
||||||
}
|
}
|
||||||
pub fn header_type(self: PciDevice) u16 {
|
pub fn header_type(self: PciDevice) u8 {
|
||||||
return self.config_read_byte(14);
|
return self.config_read(u8, 0xe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only for header_type == 0
|
||||||
pub fn subsystem(self: PciDevice) u16 {
|
pub fn subsystem(self: PciDevice) u16 {
|
||||||
return self.config_read_word(0x2e);
|
return self.config_read(u8, 0x2e);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn access(self: PciDevice, offset: u8) void {
|
pub inline fn config_read(self: PciDevice, comptime size: type, comptime offset: u8) size {
|
||||||
|
// ask for access before reading config
|
||||||
arch.outl(PCI_CONFIG_ADDRESS, self.address(offset));
|
arch.outl(PCI_CONFIG_ADDRESS, self.address(offset));
|
||||||
|
switch (size) {
|
||||||
|
// read the correct size
|
||||||
|
u8 => return arch.inb(PCI_CONFIG_DATA),
|
||||||
|
u16 => return arch.inw(PCI_CONFIG_DATA),
|
||||||
|
u32 => return arch.inl(PCI_CONFIG_DATA),
|
||||||
|
else => @compileError("pci config space only supports reading u8, u16, u32."),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config_read_byte(self: PciDevice, offset: u8) u8 {
|
|
||||||
self.access(offset);
|
|
||||||
return (arch.inb(PCI_CONFIG_DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_read_word(self: PciDevice, offset: u8) u16 {
|
|
||||||
self.access(offset);
|
|
||||||
return (arch.inw(PCI_CONFIG_DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn config_read_long(self: PciDevice, offset: u8) u32 {
|
|
||||||
self.access(offset);
|
|
||||||
return (arch.inl(PCI_CONFIG_DATA));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -114,12 +109,15 @@ const Driver = struct {
|
||||||
const name = "virtio-blk";
|
const name = "virtio-blk";
|
||||||
pub var Drivers: [1]Driver = [_]Driver{Driver{ .name = &name, .class = 0x1, .subclass = 0x0, .vendor = 0x1af4, .subsystem = 0x2, .init = virtio.init }};
|
pub var Drivers: [1]Driver = [_]Driver{Driver{ .name = &name, .class = 0x1, .subclass = 0x0, .vendor = 0x1af4, .subsystem = 0x2, .init = virtio.init }};
|
||||||
|
|
||||||
|
// TODO: factor 2 functions when anonymous fn is released
|
||||||
pub fn scan() void {
|
pub fn scan() void {
|
||||||
var slot: u5 = 0;
|
var slot: u5 = 0;
|
||||||
while (slot < 31) : (slot += 1) {
|
// 0..31
|
||||||
if (PciDevice.init(0, slot, 0)) |device| {
|
while (slot <= std.math.maxInt(u5)) : (slot += 1) {
|
||||||
|
if (PciDevice.init(0, slot, 0)) |dev| {
|
||||||
var function: u3 = 0;
|
var function: u3 = 0;
|
||||||
while (function < 8) : (function += 1) {
|
// 0..7
|
||||||
|
while (function <= std.math.maxInt(u3)) : (function += 1) {
|
||||||
if (PciDevice.init(0, slot, function)) |vf| {
|
if (PciDevice.init(0, slot, function)) |vf| {
|
||||||
if (vf.driver()) |d| d.init(vf);
|
if (vf.driver()) |d| d.init(vf);
|
||||||
}
|
}
|
||||||
|
|
@ -130,11 +128,13 @@ pub fn scan() void {
|
||||||
|
|
||||||
pub fn lspci() void {
|
pub fn lspci() void {
|
||||||
var slot: u5 = 0;
|
var slot: u5 = 0;
|
||||||
println("b:s.f c,s (ss) v d drv");
|
println("b:s.f c,s v d drv");
|
||||||
while (slot < 31) : (slot += 1) {
|
// 0..31
|
||||||
if (PciDevice.init(0, slot, 0)) |device| {
|
while (slot <= std.math.maxInt(u5)) : (slot += 1) {
|
||||||
|
if (PciDevice.init(0, slot, 0)) |dev| {
|
||||||
var function: u3 = 0;
|
var function: u3 = 0;
|
||||||
while (function < 8) : (function += 1) {
|
// 0..7
|
||||||
|
while (function <= std.math.maxInt(u3)) : (function += 1) {
|
||||||
if (PciDevice.init(0, slot, function)) |vf| {
|
if (PciDevice.init(0, slot, function)) |vf| {
|
||||||
vf.format();
|
vf.format();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
src/ps2.zig
18
src/ps2.zig
|
|
@ -69,25 +69,19 @@ const KEYMAP_US = [_][2]u8{
|
||||||
|
|
||||||
fn ps2_scancode() u8 {
|
fn ps2_scancode() u8 {
|
||||||
var scancode: u8 = 0;
|
var scancode: u8 = 0;
|
||||||
while (true) {
|
while (true) if (x86.inb(PS2_DATA) != scancode) {
|
||||||
if (x86.inb(PS2_DATA) != scancode) {
|
|
||||||
scancode = x86.inb(PS2_DATA);
|
scancode = x86.inb(PS2_DATA);
|
||||||
if (scancode > 0)
|
if (scancode > 0) return scancode;
|
||||||
return scancode;
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_isrelease(scancode: u8) bool {
|
fn key_isrelease(scancode: u8) bool {
|
||||||
return (scancode & 1 << 7 != 0);
|
return scancode & (1 << 7) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keyboard_handler() void {
|
pub fn keyboard_handler() void {
|
||||||
const scancode = ps2_scancode();
|
const scancode = ps2_scancode();
|
||||||
const isrelease = key_isrelease(scancode);
|
if (key_isrelease(scancode)) return; // don't process releases
|
||||||
if (isrelease) {
|
const shift = false; // don't know about modifiers yet
|
||||||
return;
|
|
||||||
}
|
|
||||||
const shift = false;
|
|
||||||
console.keypress(KEYMAP_US[scancode][if (shift) 1 else 0]);
|
console.keypress(KEYMAP_US[scancode][if (shift) 1 else 0]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
src/vga.zig
40
src/vga.zig
|
|
@ -3,14 +3,16 @@ const mem = @import("std").mem;
|
||||||
const arch = @import("arch/x86/lib/index.zig");
|
const arch = @import("arch/x86/lib/index.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
// VRAM buffer address in physical memory.
|
|
||||||
pub const VRAM_ADDR = 0xB8000;
|
|
||||||
pub const VRAM_SIZE = 0x8000;
|
|
||||||
// Screen size.
|
// Screen size.
|
||||||
pub const VGA_WIDTH = 80;
|
pub const VGA_WIDTH = 80;
|
||||||
pub const VGA_HEIGHT = 25;
|
pub const VGA_HEIGHT = 25;
|
||||||
pub const VGA_SIZE = VGA_WIDTH * VGA_HEIGHT;
|
pub const VGA_SIZE = VGA_WIDTH * VGA_HEIGHT;
|
||||||
pub var vga = VGA.init(VRAM_ADDR);
|
pub var vga = VGA{
|
||||||
|
.vram = @intToPtr([*]VGAEntry, 0xb8000)[0..0x4000],
|
||||||
|
.cursor = 0,
|
||||||
|
.foreground = Color.Black,
|
||||||
|
.background = Color.Brown,
|
||||||
|
};
|
||||||
|
|
||||||
// Color codes.
|
// Color codes.
|
||||||
pub const Color = enum(u4) {
|
pub const Color = enum(u4) {
|
||||||
|
|
@ -39,17 +41,13 @@ pub const VGAEntry = packed struct {
|
||||||
background: Color,
|
background: Color,
|
||||||
};
|
};
|
||||||
|
|
||||||
////
|
|
||||||
// Enable hardware cursor.
|
// Enable hardware cursor.
|
||||||
//
|
|
||||||
pub fn enableCursor() void {
|
pub fn enableCursor() void {
|
||||||
outb(0x3D4, 0x0A);
|
outb(0x3D4, 0x0A);
|
||||||
outb(0x3D5, 0x00);
|
outb(0x3D5, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
////
|
|
||||||
// Disable hardware cursor.
|
// Disable hardware cursor.
|
||||||
//
|
|
||||||
pub fn disableCursor() void {
|
pub fn disableCursor() void {
|
||||||
outb(0x3D4, 0x0A);
|
outb(0x3D4, 0x0A);
|
||||||
outb(0x3D5, 1 << 5);
|
outb(0x3D5, 1 << 5);
|
||||||
|
|
@ -72,33 +70,14 @@ fn printCallback(context: void, string: []const u8) Errors!void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VGA status.
|
// VGA status.
|
||||||
pub const VGA = struct {
|
const VGA = struct {
|
||||||
vram: []VGAEntry,
|
vram: []VGAEntry,
|
||||||
cursor: usize,
|
cursor: usize,
|
||||||
foreground: Color,
|
foreground: Color,
|
||||||
background: Color,
|
background: Color,
|
||||||
|
|
||||||
////
|
|
||||||
// Initialize the VGA status.
|
|
||||||
//
|
|
||||||
// Arguments:
|
|
||||||
// vram: The address of the VRAM buffer.
|
|
||||||
//
|
|
||||||
// Returns:
|
|
||||||
// A structure holding the VGA status.
|
|
||||||
//
|
|
||||||
pub fn init(vram: usize) VGA {
|
|
||||||
return VGA{
|
|
||||||
.vram = @intToPtr([*]VGAEntry, vram)[0..0x4000],
|
|
||||||
.cursor = 0,
|
|
||||||
.foreground = Color.Black,
|
|
||||||
.background = Color.Brown,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
////
|
////
|
||||||
// Clear the screen.
|
// Clear the screen.
|
||||||
//
|
|
||||||
pub fn clear(self: *VGA) void {
|
pub fn clear(self: *VGA) void {
|
||||||
mem.set(VGAEntry, self.vram[0..VGA_SIZE], self.entry(' '));
|
mem.set(VGAEntry, self.vram[0..VGA_SIZE], self.entry(' '));
|
||||||
|
|
||||||
|
|
@ -131,12 +110,9 @@ pub const VGA = struct {
|
||||||
self.writeChar(' ');
|
self.writeChar(' ');
|
||||||
},
|
},
|
||||||
// Backspace.
|
// Backspace.
|
||||||
// FIXME: hardcoded 8 here is horrible.
|
'\x08' => {
|
||||||
8 => {
|
|
||||||
self.cursor -= 1;
|
self.cursor -= 1;
|
||||||
// self.writeChar(' ');
|
|
||||||
self.vram[self.cursor] = self.entry(' ');
|
self.vram[self.cursor] = self.entry(' ');
|
||||||
// self.cursor -= 1;
|
|
||||||
},
|
},
|
||||||
// Any other character.
|
// Any other character.
|
||||||
else => {
|
else => {
|
||||||
|
|
|
||||||
21
src/virtio.zig
Normal file
21
src/virtio.zig
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
usingnamespace @import("vga.zig");
|
||||||
|
usingnamespace @import("pci.zig");
|
||||||
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
|
pub fn init(pci: PciDevice) void {
|
||||||
|
println("-- virtio-block init --");
|
||||||
|
pci.format();
|
||||||
|
assert(pci.header_type() == 0x0); // mass storage device
|
||||||
|
assert(pci.subsystem() == 0x2); // virtio-block
|
||||||
|
const intr_line = pci.config_read(u8, 0x3c);
|
||||||
|
const intr_pin = pci.config_read(u8, 0x3d);
|
||||||
|
const min_grant = pci.config_read(u8, 0x3e);
|
||||||
|
const max_lat = pci.config_read(u8, 0x3f);
|
||||||
|
println("{x} {} {} {}", intr_line, intr_pin, min_grant, max_lat);
|
||||||
|
println("bar0=0x{x}", pci.config_read(u32, 0x10));
|
||||||
|
println("bar1=0x{x}", pci.config_read(u32, 0x14));
|
||||||
|
println("bar2=0x{x}", pci.config_read(u32, 0x18));
|
||||||
|
println("bar3=0x{x}", pci.config_read(u32, 0x1c));
|
||||||
|
println("bar4=0x{x}", pci.config_read(u32, 0x20));
|
||||||
|
println("bar5=0x{x}", pci.config_read(u32, 0x24));
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue