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
|
- 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
1
run.sh
|
|
@ -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\
|
||||||
$*
|
$*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
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 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);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue