From f479edf1a340d2b0b264ada86ad64378b471f514 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 12 May 2019 21:10:41 +0200 Subject: [PATCH] lspci done, console ok, printf formatting ok --- README.md | 4 +- run.sh | 1 + src/arch/x86/lib/io.zig | 42 +++++++++++------- src/console.zig | 29 ++++++++++-- src/main.zig | 3 +- src/pci.zig | 97 +++++++++++++++++++++++++++++++++++++++++ src/vga.zig | 19 ++++++-- 7 files changed, 170 insertions(+), 25 deletions(-) create mode 100644 src/pci.zig diff --git a/README.md b/README.md index 5002e4b..44bacba 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,11 @@ slowly porting from rust. - vga frame buffer - ps2 keyboard driver - interrupts - - todo: terminal console + - terminal console + - lspci - todo: memory mapping - todo: cfs scheduler + - todo: smp ### dependencies diff --git a/run.sh b/run.sh index cc61c40..b09809b 100755 --- a/run.sh +++ b/run.sh @@ -12,6 +12,7 @@ qemu() { -monitor unix:${QEMU_SOCKET},server,nowait\ -display curses\ -enable-kvm\ + -device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no\ $* } diff --git a/src/arch/x86/lib/io.zig b/src/arch/x86/lib/io.zig index e6f92c9..70aac62 100644 --- a/src/arch/x86/lib/io.zig +++ b/src/arch/x86/lib/io.zig @@ -1,26 +1,22 @@ -//// -// Read a byte from a port. -// -// Arguments: -// port: Port from where to read. -// -// Returns: -// The read byte. -// pub inline fn inb(port: u16) u8 { return asm volatile ("inb %[port], %[result]" : [result] "={al}" (-> u8) : [port] "N{dx}" (port) ); } +pub inline fn inw(port: u16) u16 { + return asm volatile ("inw %[port], %[result]" + : [result] "={ax}" (-> u16) + : [port] "N{dx}" (port) + ); +} +pub inline fn inl(port: u16) u32 { + return asm volatile ("inl %[port], %[result]" + : [result] "={eax}" (-> u32) + : [port] "N{dx}" (port) + ); +} -//// -// Write a byte on a port. -// -// Arguments: -// port: Port where to write the value. -// value: Value to be written. -// pub inline fn outb(port: u16, value: u8) void { asm volatile ("outb %[value], %[port]" : @@ -28,3 +24,17 @@ pub inline fn outb(port: u16, value: u8) void { [port] "N{dx}" (port) ); } +pub inline fn outw(port: u16, value: u16) void { + asm volatile ("outw %[value], %[port]" + : + : [value] "{ax}" (value), + [port] "N{dx}" (port) + ); +} +pub inline fn outl(port: u16, value: u32) void { + asm volatile ("outl %[value], %[port]" + : + : [value] "{eax}" (value), + [port] "N{dx}" (port) + ); +} diff --git a/src/console.zig b/src/console.zig index 990bb15..f7d03e7 100644 --- a/src/console.zig +++ b/src/console.zig @@ -1,14 +1,35 @@ const interrupt = @import("arch/x86/interrupt.zig"); const x86 = @import("arch/x86/lib/index.zig"); const ps2 = @import("ps2.zig"); +const pci = @import("pci.zig"); +const std = @import("std"); +const mem = std.mem; use @import("vga.zig"); -var vga = VGA.init(VRAM_ADDR); +var command: [10]u8 = undefined; +var command_len: usize = 0; + +fn execute(com: []u8) void { + if (mem.eql(u8, com, "lspci")) pci.lspci(); +} pub fn keypress(char: u8) void { - vga.writeChar(char); - if (char == '\n') - vga.writeString("> "); + // this is a custom "readline" capped at 10 characters + switch (char) { + '\n' => { + vga.writeChar('\n'); + execute(command[0..command_len]); + vga.writeString("> "); + command_len = 0; + }, + else => { + if (command_len == 10) + return; + vga.writeChar(char); + command[command_len] = char; + command_len += 1; + }, + } } pub fn initialize() void { diff --git a/src/main.zig b/src/main.zig index c4c4e8e..c45afbc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,7 @@ use @import("multiboot.zig"); -const console = @import("console.zig"); +const pci = @import("pci.zig"); const arch = @import("arch/x86/lib/index.zig"); +const console = @import("console.zig"); // platform independant initialization pub fn kmain() noreturn { diff --git a/src/pci.zig b/src/pci.zig new file mode 100644 index 0000000..131e52a --- /dev/null +++ b/src/pci.zig @@ -0,0 +1,97 @@ +const arch = @import("arch/x86/lib/index.zig"); + +const PCI_CONFIG_ADDRESS = 0xCF8; +const PCI_CONFIG_DATA = 0xCFC; +const vga = @import("vga.zig"); + +pub const PciAddress = packed struct { + offset: u8, + function: u3, + slot: u5, + bus: u8, + reserved: u7, + enable: u1, +}; + +pub const PciDevice = struct { + bus: u8, + slot: u5, + function: u3, + device: u16, + vendor: u16, + class: u8, + subclass: u8, + header_type: u8, + + pub fn init(bus: u8, slot: u5, function: u3) ?PciDevice { + var pcidevice = PciDevice{ + .bus = bus, + .slot = slot, + .function = function, + .device = undefined, + .class = undefined, + .subclass = undefined, + .header_type = undefined, + .vendor = undefined, + }; + pcidevice.vendor = pci_config_read_word(pcidevice, 0); + if (pcidevice.vendor == 0xffff) + return null; + pcidevice.device = pci_config_read_word(pcidevice, 2); + pcidevice.subclass = pci_config_read_byte(pcidevice, 10); + pcidevice.class = pci_config_read_byte(pcidevice, 11); + pcidevice.header_type = pci_config_read_byte(pcidevice, 14); + return (pcidevice); + } + + pub fn address(self: PciDevice, offset: u8) u32 { + var addr = PciAddress{ + .enable = 1, + .reserved = 0, + .bus = self.bus, + .slot = self.slot, + .function = self.function, + .offset = offset, + }; + return (@bitCast(u32, addr)); + } + + pub fn format(self: PciDevice) void { + vga.printf("{}:{}.{} {x},{x}: {x} {x}\n", self.bus, self.slot, self.function, self.class, self.subclass, self.vendor, self.device); + } + + pub fn access(self: PciDevice, offset: u8) void { + arch.outl(PCI_CONFIG_ADDRESS, self.address(offset)); + } + + pub fn pci_config_read_byte(self: PciDevice, offset: u8) u8 { + self.access(offset); + return (arch.inb(PCI_CONFIG_DATA)); + } + + pub fn pci_config_read_word(self: PciDevice, offset: u8) u16 { + self.access(offset); + return (arch.inw(PCI_CONFIG_DATA)); + } + + pub fn pci_config_read_long(self: PciDevice, offset: u8) u32 { + self.access(offset); + return (arch.inl(PCI_CONFIG_DATA)); + } +}; + +pub fn lspci() void { + var slot: u5 = 0; + while (true) { + if (PciDevice.init(0, slot, 0)) |device| { + device.format(); + var function: u3 = 0; + while (true) { + if (PciDevice.init(0, slot, function)) |vf| + vf.format(); + if (function == 7) break else function += 1; + } + } + if (slot == 31) break else slot += 1; + } +} diff --git a/src/vga.zig b/src/vga.zig index 017a08a..3a73c71 100644 --- a/src/vga.zig +++ b/src/vga.zig @@ -1,6 +1,7 @@ const builtin = @import("builtin"); const mem = @import("std").mem; const arch = @import("arch/x86/lib/index.zig"); +const std = @import("std"); // VRAM buffer address in physical memory. pub const VRAM_ADDR = 0xB8000; @@ -9,6 +10,7 @@ pub const VRAM_SIZE = 0x8000; pub const VGA_WIDTH = 80; pub const VGA_HEIGHT = 25; pub const VGA_SIZE = VGA_WIDTH * VGA_HEIGHT; +pub var vga = VGA.init(VRAM_ADDR); // Color codes. pub const Color = enum(u4) { @@ -53,6 +55,15 @@ pub fn disableCursor() void { outb(0x3D5, 1 << 5); } +const Errors = error{}; +pub fn printf(comptime format: []const u8, args: ...) void { + var a = std.fmt.format({}, Errors, printCallback, format, args); +} + +fn printCallback(context: void, string: []const u8) Errors!void { + vga.writeString(string); +} + // VGA status. pub const VGA = struct { vram: []VGAEntry, @@ -116,8 +127,9 @@ pub const VGA = struct { // FIXME: hardcoded 8 here is horrible. 8 => { self.cursor -= 1; - self.writeChar(' '); - self.cursor -= 1; + // self.writeChar(' '); + self.vram[self.cursor] = self.entry(' '); + // self.cursor -= 1; }, // Any other character. else => { @@ -125,6 +137,7 @@ pub const VGA = struct { self.cursor += 1; }, } + self.updateCursor(); } //// @@ -161,7 +174,7 @@ pub const VGA = struct { // Update the position of the hardware cursor. // Use the software cursor as the source of truth. // - fn updateCursor(self: *const VGA) void { + pub fn updateCursor(self: *const VGA) void { arch.outb(0x3D4, 0x0F); arch.outb(0x3D5, @truncate(u8, self.cursor)); arch.outb(0x3D4, 0x0E);