lspci done, console ok, printf formatting ok

This commit is contained in:
Jack Halford 2019-05-12 21:10:41 +02:00
parent 0273c9a8c8
commit f479edf1a3
7 changed files with 170 additions and 25 deletions

View file

@ -7,9 +7,11 @@ slowly porting from rust.
- vga frame buffer - vga frame buffer
- ps2 keyboard driver - ps2 keyboard driver
- interrupts - interrupts
- todo: terminal console - terminal console
- lspci
- todo: memory mapping - todo: memory mapping
- todo: cfs scheduler - todo: cfs scheduler
- todo: smp
### dependencies ### dependencies

1
run.sh
View file

@ -12,6 +12,7 @@ qemu() {
-monitor unix:${QEMU_SOCKET},server,nowait\ -monitor unix:${QEMU_SOCKET},server,nowait\
-display curses\ -display curses\
-enable-kvm\ -enable-kvm\
-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no\
$* $*
} }

View file

@ -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 { pub inline fn inb(port: u16) u8 {
return asm volatile ("inb %[port], %[result]" return asm volatile ("inb %[port], %[result]"
: [result] "={al}" (-> u8) : [result] "={al}" (-> u8)
: [port] "N{dx}" (port) : [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 { pub inline fn outb(port: u16, value: u8) void {
asm volatile ("outb %[value], %[port]" asm volatile ("outb %[value], %[port]"
: :
@ -28,3 +24,17 @@ pub inline fn outb(port: u16, value: u8) void {
[port] "N{dx}" (port) [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)
);
}

View file

@ -1,14 +1,35 @@
const interrupt = @import("arch/x86/interrupt.zig"); const interrupt = @import("arch/x86/interrupt.zig");
const x86 = @import("arch/x86/lib/index.zig"); const x86 = @import("arch/x86/lib/index.zig");
const ps2 = @import("ps2.zig"); const ps2 = @import("ps2.zig");
const pci = @import("pci.zig");
const std = @import("std");
const mem = std.mem;
use @import("vga.zig"); 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 { pub fn keypress(char: u8) void {
vga.writeChar(char); // this is a custom "readline" capped at 10 characters
if (char == '\n') switch (char) {
'\n' => {
vga.writeChar('\n');
execute(command[0..command_len]);
vga.writeString("> "); 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 { pub fn initialize() void {

View file

@ -1,6 +1,7 @@
use @import("multiboot.zig"); use @import("multiboot.zig");
const console = @import("console.zig"); const pci = @import("pci.zig");
const arch = @import("arch/x86/lib/index.zig"); const arch = @import("arch/x86/lib/index.zig");
const console = @import("console.zig");
// platform independant initialization // platform independant initialization
pub fn kmain() noreturn { pub fn kmain() noreturn {

97
src/pci.zig Normal file
View file

@ -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;
}
}

View file

@ -1,6 +1,7 @@
const builtin = @import("builtin"); const builtin = @import("builtin");
const mem = @import("std").mem; 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");
// VRAM buffer address in physical memory. // VRAM buffer address in physical memory.
pub const VRAM_ADDR = 0xB8000; pub const VRAM_ADDR = 0xB8000;
@ -9,6 +10,7 @@ pub const VRAM_SIZE = 0x8000;
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);
// Color codes. // Color codes.
pub const Color = enum(u4) { pub const Color = enum(u4) {
@ -53,6 +55,15 @@ pub fn disableCursor() void {
outb(0x3D5, 1 << 5); 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. // VGA status.
pub const VGA = struct { pub const VGA = struct {
vram: []VGAEntry, vram: []VGAEntry,
@ -116,8 +127,9 @@ pub const VGA = struct {
// FIXME: hardcoded 8 here is horrible. // FIXME: hardcoded 8 here is horrible.
8 => { 8 => {
self.cursor -= 1; self.cursor -= 1;
self.writeChar(' '); // self.writeChar(' ');
self.cursor -= 1; self.vram[self.cursor] = self.entry(' ');
// self.cursor -= 1;
}, },
// Any other character. // Any other character.
else => { else => {
@ -125,6 +137,7 @@ pub const VGA = struct {
self.cursor += 1; self.cursor += 1;
}, },
} }
self.updateCursor();
} }
//// ////
@ -161,7 +174,7 @@ pub const VGA = struct {
// Update the position of the hardware cursor. // Update the position of the hardware cursor.
// Use the software cursor as the source of truth. // 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(0x3D4, 0x0F);
arch.outb(0x3D5, @truncate(u8, self.cursor)); arch.outb(0x3D5, @truncate(u8, self.cursor));
arch.outb(0x3D4, 0x0E); arch.outb(0x3D4, 0x0E);