lspci done, console ok, printf formatting ok
This commit is contained in:
parent
0273c9a8c8
commit
f479edf1a3
7 changed files with 170 additions and 25 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
1
run.sh
1
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\
|
||||
$*
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
// 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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
97
src/pci.zig
Normal file
97
src/pci.zig
Normal 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;
|
||||
}
|
||||
}
|
||||
19
src/vga.zig
19
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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue