From 902aa136c6b982f8fc823815c2cf413b3b8e369d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 14 Sep 2019 15:49:57 +0200 Subject: [PATCH] PIT configured, preparing for scheduling --- src/arch/x86/idt.zig | 10 ++++++++-- src/arch/x86/index.zig | 1 + src/arch/x86/interrupt.zig | 32 ++++++++++++++++++++--------- src/arch/x86/isr.zig | 11 ++++++---- src/console.zig | 10 +++++++++- src/index.zig | 1 + src/main.zig | 21 ------------------- src/pci/virtio.zig | 41 ++++++++++++++++++++++++++++++-------- src/time.zig | 14 +++++++++++++ src/vga.zig | 18 +++++++++++++++-- 10 files changed, 112 insertions(+), 47 deletions(-) create mode 100644 src/time.zig diff --git a/src/arch/x86/idt.zig b/src/arch/x86/idt.zig index 32c29a7..0b9d9f8 100644 --- a/src/arch/x86/idt.zig +++ b/src/arch/x86/idt.zig @@ -50,8 +50,14 @@ pub fn setGate(n: u8, flags: u8, offset: extern fn () void) void { // Initialize the Interrupt Descriptor Table. pub fn initialize() void { - // configure PIC and set ISRs - interrupt.initialize(); + // configure PIC + interrupt.remapPIC(); + interrupt.configPIT(); + // install ISRs + isr.install_exceptions(); + isr.install_irqs(); + isr.install_syscalls(); + interrupt.registerIRQ(0, interrupt.pit_handler); // load IDT lidt(@ptrToInt(&idtr)); diff --git a/src/arch/x86/index.zig b/src/arch/x86/index.zig index ea3be95..8cf9cea 100644 --- a/src/arch/x86/index.zig +++ b/src/arch/x86/index.zig @@ -1,5 +1,6 @@ pub usingnamespace @import("../../vga.zig"); pub const multiboot = @import("../../multiboot.zig"); +pub const time = @import("../../time.zig"); pub usingnamespace @import("lib/io.zig"); pub usingnamespace @import("lib/instructions.zig"); diff --git a/src/arch/x86/interrupt.zig b/src/arch/x86/interrupt.zig index 5b991a4..4a3b001 100644 --- a/src/arch/x86/interrupt.zig +++ b/src/arch/x86/interrupt.zig @@ -1,6 +1,4 @@ usingnamespace @import("index.zig"); -// const x86 = @import("index.zig"); -// const isr = @import("isr.zig"); // PIC ports. const PIC1_CMD = 0x20; @@ -16,6 +14,11 @@ const ICW1_ICW4 = 0x01; const ICW4_8086 = 0x01; // write 0 to wait const WAIT_PORT = 0x80; +// PIT Channels +const PIT_CHAN0 = 0x40; +const PIT_CHAN1 = 0x41; +const PIT_CHAN2 = 0x42; +const PIT_CMD = 0x43; // Interrupt Vector offsets of exceptions. const EXCEPTION_0 = 0; const EXCEPTION_31 = EXCEPTION_0 + 31; @@ -132,7 +135,7 @@ pub fn registerIRQ(irq: u8, handler: fn () void) void { maskIRQ(irq, false); // Unmask the IRQ. } -fn remapPIC() void { +pub fn remapPIC() void { // ICW1: start initialization sequence. outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4); picwait(); @@ -180,10 +183,21 @@ pub fn maskIRQ(irq: u8, mask: bool) void { const new = inb(port); // Retrieve the current mask. } -//// -// Initialize interrupts. -// -pub fn initialize() void { - remapPIC(); - isr.install(); +// configures the chan0 with a rate generator, which will trigger irq0 +pub fn configPIT() void { + const chanNum = 0; + const chan = PIT_CHAN0; + const divisor = 2685; + const LOHI = 0b11; // bit4 | bit5 + const PITMODE_RATE_GEN = 0x2; + outb(PIT_CMD, chanNum << 6 | LOHI << 4 | PITMODE_RATE_GEN << 1); + outb(PIT_CHAN0, divisor & 0xff); + outb(PIT_CHAN0, divisor >> 8); +} + +pub fn pit_handler() void { + // pit freq = 1.193182 MHz + // chan0 divisor = 2685 + // PIT_RATE in us + time.increment(2251); } diff --git a/src/arch/x86/isr.zig b/src/arch/x86/isr.zig index 7a4fd05..3ef0f45 100644 --- a/src/arch/x86/isr.zig +++ b/src/arch/x86/isr.zig @@ -87,9 +87,8 @@ pub export var context: *volatile Context = undefined; //// // Install the Interrupt Service Routines in the IDT. // -pub fn install() void { +pub fn install_exceptions() void { // Exceptions. - idt.setGate(0, idt.INTERRUPT_GATE, isr0); idt.setGate(1, idt.INTERRUPT_GATE, isr1); idt.setGate(2, idt.INTERRUPT_GATE, isr2); idt.setGate(3, idt.INTERRUPT_GATE, isr3); @@ -121,8 +120,10 @@ pub fn install() void { idt.setGate(29, idt.INTERRUPT_GATE, isr29); idt.setGate(30, idt.INTERRUPT_GATE, isr30); idt.setGate(31, idt.INTERRUPT_GATE, isr31); +} - // IRQs. +// IRQs. +pub fn install_irqs() void { idt.setGate(32, idt.INTERRUPT_GATE, isr32); idt.setGate(33, idt.INTERRUPT_GATE, isr33); idt.setGate(34, idt.INTERRUPT_GATE, isr34); @@ -139,7 +140,9 @@ pub fn install() void { idt.setGate(45, idt.INTERRUPT_GATE, isr45); idt.setGate(46, idt.INTERRUPT_GATE, isr46); idt.setGate(47, idt.INTERRUPT_GATE, isr47); +} - // Syscalls. +// Syscalls. +pub fn install_syscalls() void { idt.setGate(128, idt.SYSCALL_GATE, isr128); } diff --git a/src/console.zig b/src/console.zig index 8cf854c..cbc47b5 100644 --- a/src/console.zig +++ b/src/console.zig @@ -6,6 +6,8 @@ var command_len: usize = 0; fn execute(com: []u8) void { if (@import("std").mem.eql(u8, com, "lspci")) pci.lspci(); if (@import("std").mem.eql(u8, com, "paging")) x86.paging.addrspace(); + if (@import("std").mem.eql(u8, com, "uptime")) time.uptime(); + if (@import("std").mem.eql(u8, com, "topbar")) topbar(); } pub fn keypress(char: u8) void { @@ -17,8 +19,14 @@ pub fn keypress(char: u8) void { print("> "); command_len = 0; }, - '\x08' => return, //backspace '\x00' => return, + '\x08' => { + // backspace + if (command_len == 0) return; + vga.writeChar(char); + command_len -= 1; + command[command_len] = '\x00'; + }, else => { // general case if (command_len == 10) return; diff --git a/src/index.zig b/src/index.zig index cce2ad0..f748201 100644 --- a/src/index.zig +++ b/src/index.zig @@ -7,3 +7,4 @@ pub const console = @import("console.zig"); pub const pci = @import("pci/pci.zig"); pub const ps2 = @import("ps2.zig"); pub const x86 = @import("arch/x86/index.zig"); +pub const time = @import("time.zig"); diff --git a/src/main.zig b/src/main.zig index 3a0e203..ff6a638 100644 --- a/src/main.zig +++ b/src/main.zig @@ -16,27 +16,6 @@ export const multiboot_header align(4) linksection(".multiboot") = multiboot: { }; }; -// export var stack_bytes: [16 * 1024]u8 align(16) linksection(".bss") = undefined; -// const stack_bytes_slice = stack_bytes[0..]; - -// linker.ld entrypoint -// export nakedcc fn __start() noreturn { -// // eax -> multiboot magic -// // ebx -> multiboot info -// const magic = asm volatile ("mov %[ret], %eax" -// : [ret] "=" (-> u32) -// ); -// const info = asm volatile ("" -// : [ret] "=" (-> u32) -// ); -// clear(); -// println("--- {x} ---", magic); -// println("--- {x} ---", info); -// // @newStackCall(stack_bytes_slice, kmain, magic, @intToPtr(*const multiboot.MultibootInfo, info)); -// @newStackCall(stack_bytes_slice, kmain, magic); -// // @newStackCall(stack_bytes_slice, kmain); -// } - // arch independant initialization export fn kmain(magic: u32, info: *const multiboot.MultibootInfo) noreturn { assert(magic == multiboot.MULTIBOOT_BOOTLOADER_MAGIC); diff --git a/src/pci/virtio.zig b/src/pci/virtio.zig index a281317..52720de 100644 --- a/src/pci/virtio.zig +++ b/src/pci/virtio.zig @@ -12,12 +12,37 @@ pub fn init(dev: PciDevice) void { const max_lat = dev.config_read(u8, 0x3f); println("{x} {} {} {}", intr_line, intr_pin, min_grant, max_lat); - println("dev features =0x{x}", dev.config_read(u32, 0x10)); - println("guest features=0x{x}", dev.config_read(u32, 0x14)); - println("queue addr =0x{x}", dev.config_read(u32, 0x18)); - println("queue size =0x{x}", dev.config_read(u16, 0x1c)); - println("queue select =0x{x}", dev.config_read(u16, 0x1e)); - println("queue notify =0x{x}", dev.config_read(u16, 0x20)); - println("device status =0x{x}", dev.config_read(u8, 0x22)); - println("isr status =0x{x}", dev.config_read(u8, 0x23)); + // all virtio + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | dev features | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | guest features | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | queue address | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | queue size | queue notify | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | device status | isr status | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + // println("dev feats =0x{x}", dev.config_read(u32, 0x10)); + // println("guest feats =0x{x}", dev.config_read(u32, 0x14)); + // println("queue addr =0x{x}", dev.config_read(u32, 0x18)); + // println("queue size =0x{x}", dev.config_read(u16, 0x1c)); + // println("queue select =0x{x}", dev.config_read(u16, 0x1e)); + // println("queue notify =0x{x}", dev.config_read(u16, 0x20)); + // println("device status=0x{x}", dev.config_read(u8, 0x22)); + // println("isr status =0x{x}", dev.config_read(u8, 0x23)); + + // all virtio-block + // println("Total Sector Count={}", dev.config_read(u32, 0x24)); + // println("Total Sector Count={}", dev.config_read(u32, 0x28)); + // println("Maximum Seg Size ={}", dev.config_read(u16, 0x2c)); + // println("Maximum Seg Count ={}", dev.config_read(u32, 0x30)); + // println("Cylinder Count ={}", dev.config_read(u16, 0x34)); + // println("Head Count ={}", dev.config_read(u8, 0x36)); + // println("Sector Count ={}", dev.config_read(u8, 0x37)); + // println("Block Length ={}", dev.config_read(u8, 0x38)); } diff --git a/src/time.zig b/src/time.zig new file mode 100644 index 0000000..d33ad5e --- /dev/null +++ b/src/time.zig @@ -0,0 +1,14 @@ +usingnamespace @import("index.zig"); + +pub var offset_s: u32 = 0; +pub var offset_us: u32 = 0; +pub fn increment(value: u32) void { + const sum = offset_us + value; + offset_s += sum / 1000000; + offset_us = sum % 1000000; +} + +pub fn uptime() void { + const offset_ms = offset_us / 1000; + println("uptime: {}.{:.3}", offset_s, offset_ms); +} diff --git a/src/vga.zig b/src/vga.zig index fa2d1c8..3c72299 100644 --- a/src/vga.zig +++ b/src/vga.zig @@ -1,3 +1,5 @@ +// usingnamespace @import("index.zig"); +const time = @import("time.zig"); const x86 = @import("arch/x86/index.zig"); const std = @import("std"); @@ -7,7 +9,7 @@ pub const VGA_HEIGHT = 25; pub const VGA_SIZE = VGA_WIDTH * VGA_HEIGHT; pub var vga = VGA{ .vram = @intToPtr([*]VGAEntry, 0xb8000)[0..0x4000], - .cursor = 0, + .cursor = 80 * 2, .foreground = Color.Black, .background = Color.Brown, }; @@ -62,6 +64,18 @@ pub fn println(comptime format: []const u8, args: ...) void { pub fn clear() void { vga.clear(); } +pub fn topbar() void { + const cursor = vga.cursor; + const bg = vga.background; + vga.cursor = 0; + vga.background = Color.Red; + + const offset_ms = time.offset_us / 1000; + println("{}.{}", time.offset_s, offset_ms / 10); + + vga.cursor = cursor; + vga.background = bg; +} fn printCallback(context: void, string: []const u8) Errors!void { vga.writeString(string); @@ -79,7 +93,7 @@ const VGA = struct { pub fn clear(self: *VGA) void { std.mem.set(VGAEntry, self.vram[0..VGA_SIZE], self.entry(' ')); - self.cursor = 0; + self.cursor = 80; // skip 1 line for topbar self.updateCursor(); }