lspci, console refactor
This commit is contained in:
parent
85afa2b437
commit
c9ad4e9e58
10 changed files with 250 additions and 327 deletions
|
|
@ -126,17 +126,9 @@ impl Iterator for ACPISDTIter {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_init() -> Result<(), &'static str> {
|
||||
if unsafe { ACPI.valid } {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("ACPI is not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
/// Initalized the ACPI module
|
||||
pub fn init() -> Result<(), &'static str> {
|
||||
if let Ok(()) = is_init() {
|
||||
if unsafe{ACPI.valid} {
|
||||
return Ok(());
|
||||
}
|
||||
unsafe { ACPI.init() }
|
||||
|
|
@ -144,7 +136,7 @@ pub fn init() -> Result<(), &'static str> {
|
|||
|
||||
/// Load the ACPI module, addr given is a ptr to RSDP
|
||||
pub fn load(rsdp_addr: u32) -> Result<(), &'static str> {
|
||||
if let Ok(()) = is_init() {
|
||||
if unsafe{ACPI.valid} {
|
||||
return Ok(());
|
||||
}
|
||||
unsafe { ACPI.load(rsdp_addr) }
|
||||
|
|
@ -152,32 +144,30 @@ pub fn load(rsdp_addr: u32) -> Result<(), &'static str> {
|
|||
|
||||
/// Proceed to ACPI shutdown
|
||||
/// This function doesn't work with Virtual Box yet
|
||||
pub fn shutdown() -> Result<(), &'static str> {
|
||||
is_init()?;
|
||||
dsdt::shutdown(fadt::get_controlblock()?)
|
||||
pub fn shutdown() {
|
||||
if unsafe{ACPI.valid} { return }
|
||||
dsdt::shutdown(fadt::get_controlblock().unwrap());
|
||||
}
|
||||
|
||||
/// Proceed to ACPI reboot
|
||||
/// This function need ACPI in v2
|
||||
pub fn reboot() -> Result<(), &'static str> {
|
||||
is_init()?;
|
||||
pub fn reboot() {
|
||||
if unsafe {!ACPI.valid} {
|
||||
println!("ACPI not initialized");
|
||||
}
|
||||
if unsafe { ACPI.v2 } {
|
||||
fadt::reboot()
|
||||
fadt::reboot().unwrap()
|
||||
} else {
|
||||
Err("ACPI reboot only available in ACPI v2+")
|
||||
println!("ACPI reboot only available in ACPI v2+");
|
||||
}
|
||||
}
|
||||
|
||||
/// Display state of ACPI
|
||||
pub fn info() -> Result<(), &'static str> {
|
||||
is_init()?;
|
||||
println!(
|
||||
"ACPI STATE:\n {}",
|
||||
if fadt::is_enable()? {
|
||||
"ENABLED"
|
||||
} else {
|
||||
"DISABLED"
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
pub fn info() {
|
||||
if unsafe { !ACPI.valid } { println!("ACPI not initialized"); return }
|
||||
match fadt::is_enable() {
|
||||
Ok(True) => println!("ACPI is disabled"),
|
||||
Ok(False) => println!("ACPI is disabled"),
|
||||
Err(msg) => println!("error while checking ACPI")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
|
|||
|
||||
#[alloc_error_handler]
|
||||
fn foo(_: core::alloc::Layout) -> ! {
|
||||
panic!();
|
||||
panic!("alloc_error_handler");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
extern crate raw_cpuid;
|
||||
|
||||
use core::fmt::Result;
|
||||
|
||||
use self::raw_cpuid::CpuId;
|
||||
|
||||
pub fn cpu_info() -> Result {
|
||||
pub fn cpu_info() {
|
||||
let cpuid = CpuId::new();
|
||||
|
||||
if let Some(info) = cpuid.get_vendor_info() {
|
||||
|
|
@ -285,6 +283,4 @@ pub fn cpu_info() -> Result {
|
|||
};
|
||||
println!("");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
|
|||
// parse multiboot2 info
|
||||
let boot_info = multiboot2::load(multiboot_info_addr);
|
||||
|
||||
// println!("{:?}", boot_info);
|
||||
// flush!();
|
||||
// asm!("hlt");
|
||||
|
||||
// ACPI must be intialized BEFORE paging is active
|
||||
if let Some(rsdp) = boot_info.rsdp_v2_tag() {
|
||||
acpi::load(rsdp).expect("ACPI failed");
|
||||
|
|
@ -116,3 +112,30 @@ pub unsafe fn usermode(ip: u32, sp: u32) -> ! {
|
|||
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
/// Dump control registers
|
||||
pub fn regs() {
|
||||
use x86::registers::control::*;
|
||||
use x86::instructions::tables::tr;
|
||||
use x86::instructions::segmentation::*;
|
||||
use x86::registers::flags::*;
|
||||
use x86::structures::gdt;
|
||||
println!("cr0 = {:?}", Cr0::read());
|
||||
println!("cr3 = {:?}", Cr3::read());
|
||||
println!("cr4 = {:?}", Cr4::read());
|
||||
println!("flags= {:?}", flags());
|
||||
println!("tr = {:?}", tr());
|
||||
println!("ss = {:?}", ss());
|
||||
println!("cs = {:?}", cs());
|
||||
println!("ds = {:?}", ds());
|
||||
println!("es = {:?}", es());
|
||||
println!("fs = {:?}", fs());
|
||||
println!("gs = {:?}", gs());
|
||||
unsafe {
|
||||
println!(
|
||||
"tss = {:#?}",
|
||||
gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize])
|
||||
);
|
||||
}
|
||||
flush!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,49 @@
|
|||
extern crate core;
|
||||
// extern crate multiboot2;
|
||||
|
||||
use acpi;
|
||||
use time;
|
||||
use keyboard::PS2;
|
||||
use core::char;
|
||||
use vga::*;
|
||||
use alloc::collections::BTreeMap;
|
||||
|
||||
pub static mut CONSOLE: Console = self::Console::new();
|
||||
|
||||
lazy_static! {
|
||||
static ref COMMANDS: BTreeMap<&'static str, fn()> = {
|
||||
let mut commands = BTreeMap::new();
|
||||
commands.insert("help", self::help as fn());
|
||||
|
||||
// ACPI
|
||||
commands.insert("acpi", ::acpi::info as fn());
|
||||
commands.insert("reboot", ::acpi::reboot as fn());
|
||||
commands.insert("shutdown", ::acpi::shutdown as fn());
|
||||
|
||||
// time
|
||||
commands.insert("uptime", ::time::uptime as fn());
|
||||
|
||||
// cpu
|
||||
use arch::x86;
|
||||
commands.insert("cpu", x86::devices::cpu::cpu_info as fn());
|
||||
commands.insert("regs", x86::regs as fn());
|
||||
commands.insert("int3", ::x86::instructions::interrupts::int3 as fn());
|
||||
|
||||
//memory
|
||||
commands.insert("stack", ::memory::print_stack as fn());
|
||||
commands.insert("page_fault", ::memory::page_fault as fn());
|
||||
commands.insert("overflow", ::memory::overflow as fn());
|
||||
commands.insert("overflow", ::memory::overflow as fn());
|
||||
|
||||
//pci
|
||||
commands.insert("lspci", ::pci::lspci as fn());
|
||||
commands
|
||||
};
|
||||
}
|
||||
|
||||
fn help() {
|
||||
println!("The following commands are available:");
|
||||
for (key, val) in COMMANDS.iter() {
|
||||
println!("{}", key);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Console {
|
||||
command: [u8; 10],
|
||||
command_len: usize,
|
||||
|
|
@ -54,11 +89,7 @@ impl Console {
|
|||
}
|
||||
b'\n' => {
|
||||
unsafe { VGA.write_byte(b'\n'); }
|
||||
if let Err(msg) = self.exec() {
|
||||
set_color!(Red);
|
||||
println!("{}", msg);
|
||||
set_color!();
|
||||
}
|
||||
self.exec();
|
||||
self.command_len = 0;
|
||||
self.prompt();
|
||||
}
|
||||
|
|
@ -73,256 +104,27 @@ impl Console {
|
|||
self.command_len += 1;
|
||||
}
|
||||
}
|
||||
flush!();
|
||||
unsafe { VGA.flush(); }
|
||||
}
|
||||
|
||||
|
||||
fn get_command(&self) -> Result<&str, &'static str> {
|
||||
fn get_command(&self) -> Result<fn(), &'static str> {
|
||||
match core::str::from_utf8(&self.command) {
|
||||
Ok(y) => Ok(&y[..self.command_len]),
|
||||
Ok(y) => {
|
||||
if let Some(command) = COMMANDS.get(&y[..self.command_len]) {
|
||||
Ok(*command)
|
||||
} else {
|
||||
Err("Command not found, try help")
|
||||
}
|
||||
},
|
||||
Err(_) => Err("Command is not utf8"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec(&self) -> core::result::Result<(), &'static str> {
|
||||
pub fn exec(&self) {
|
||||
let command = self.get_command();
|
||||
if let Err(msg) = command {
|
||||
return Err(msg)
|
||||
}
|
||||
match command.unwrap() {
|
||||
"help" | "h" => self::help(),
|
||||
|
||||
// multiboot
|
||||
// "memory" => self::mb2_memory(),
|
||||
// "multiboot" => self::mb2_info(),
|
||||
// "sections" => self::mb2_sections(),
|
||||
|
||||
// ACPI
|
||||
"acpi" => self::acpi_info(),
|
||||
"reboot" => self::reboot(),
|
||||
"shutdown" | "halt" | "q" => self::shutdown(),
|
||||
|
||||
// x86 specific
|
||||
"stack" => self::print_stack(),
|
||||
"regs" => self::regs(),
|
||||
"cpu" => self::cpu(),
|
||||
"int3" => self::int3(),
|
||||
"overflow" => self::overflow(),
|
||||
"page_fault" => self::page_fault(),
|
||||
|
||||
// time
|
||||
"uptime" => self::uptime(),
|
||||
|
||||
_ => Err("Command unknown. (try help)"),
|
||||
match command {
|
||||
Err(msg) => println!("{}", msg),
|
||||
Ok(func) => (func)(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn help() -> Result<(), &'static str> {
|
||||
println!("help | h => print this help");
|
||||
// println!("memory => Print memory areas");
|
||||
// println!("multiboot => Print multiboot information");
|
||||
// println!("sections => Print elf sections");
|
||||
println!("reboot => reboot");
|
||||
println!("shutdown | halt | q => acpi shutdown");
|
||||
println!("acpi => acpi state");
|
||||
println!("stack => print kernel stack in a fancy way");
|
||||
println!("regs => print controle register");
|
||||
println!("cpu => print cpu information");
|
||||
println!("overflow => triggers a stack overflow");
|
||||
println!("page_fault => triggers a page fault on 0xdead");
|
||||
flush!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uptime() -> Result<(), &'static str> {
|
||||
let mut offset = time::OFFSET.lock();
|
||||
fprintln!("{}s", offset.0 + offset.1 / 1_000_000);
|
||||
flush!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
use x86::instructions::halt;
|
||||
/// Reboot the kernel
|
||||
///
|
||||
/// If reboot failed, will loop on a halt cmd
|
||||
///
|
||||
fn reboot() -> ! {
|
||||
match acpi::reboot() {
|
||||
Err(msg) => println!("{}", msg),
|
||||
_ => println!("Unable to perform ACPI reboot."),
|
||||
}
|
||||
flush!();
|
||||
unsafe { PS2.ps2_8042_reset() }; // TODO unsafe
|
||||
println!("Unable to perform 8042 reboot. Kernel will be halted");
|
||||
flush!();
|
||||
halt();
|
||||
}
|
||||
|
||||
/// Shutdown the kernel
|
||||
///
|
||||
/// If shutdown is performed but failed, will loop on a halt cmd
|
||||
/// If shutdown cannot be called, return a Err(&str)
|
||||
///
|
||||
fn shutdown() -> ! {
|
||||
match acpi::shutdown() {
|
||||
Err(msg) => println!("{}", msg),
|
||||
_ => println!("Unable to perform ACPI shutdown. Kernel will be halted"),
|
||||
}
|
||||
flush!();
|
||||
halt();
|
||||
}
|
||||
|
||||
fn hexdump(start: usize, end: usize) {
|
||||
let mut address = 0;
|
||||
let data = unsafe { core::slice::from_raw_parts_mut(start as *mut u8, end - start) };
|
||||
while address <= data.len() {
|
||||
let next_end = core::cmp::min(address + 16, data.len());
|
||||
print_line(&data[address..next_end], address + start);
|
||||
address = address + 16;
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
|
||||
fn is_control(c: char) -> bool {
|
||||
!(c >= ' ' && c <= '~')
|
||||
}
|
||||
|
||||
fn print_line(line: &[u8], address: usize) {
|
||||
print!("\n{:#08x}: ", address);
|
||||
for byte in line {
|
||||
print!("{:02x} ", *byte);
|
||||
}
|
||||
let length: usize = 16 - line.len();
|
||||
for _ in 0..length {
|
||||
print!(" ");
|
||||
}
|
||||
print!("|");
|
||||
for byte in line {
|
||||
match is_control(*byte as char) {
|
||||
true => print!("."),
|
||||
false => print!("{}", *byte as char),
|
||||
};
|
||||
}
|
||||
print!("|");
|
||||
}
|
||||
|
||||
/// Print the kernel stack
|
||||
pub fn print_stack() -> Result<(), &'static str> {
|
||||
let esp: usize;
|
||||
let ebp: usize;
|
||||
unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) };
|
||||
println!("esp = {:#x}", esp);
|
||||
println!("ebp = {:#x}", ebp);
|
||||
println!("size = {:#X} bytes", ebp - esp);
|
||||
hexdump(esp, ebp);
|
||||
flush!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// fn mb2_memory() -> Result <(), &'static str> {
|
||||
// let boot_info = ::multiboot2::boot_info();
|
||||
|
||||
// let memory_map_tag = boot_info.memory_map_tag()
|
||||
// .expect("Memory map tag required");
|
||||
|
||||
// println!("memory areas:");
|
||||
// for area in memory_map_tag.memory_areas() {
|
||||
// println!(" start: 0x{:x}, length: 0x{:x}",
|
||||
// area.start_address(), area.size());
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// fn mb2_sections() -> Result <(), &'static str> {
|
||||
// let boot_info = ::multiboot2::boot_info();
|
||||
|
||||
// let elf_sections_tag = boot_info.elf_sections_tag()
|
||||
// .expect("Elf-sections tag required");
|
||||
|
||||
// println!("kernel sections:");
|
||||
// for section in elf_sections_tag.sections() {
|
||||
// println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}",
|
||||
// section.name(), section.start_address(), section.size(), section.flags());
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// fn mb2_info() -> Result <(), &'static str> {
|
||||
// let boot_info = context::boot_info();
|
||||
|
||||
// let command_line_tag = boot_info.command_line_tag()
|
||||
// .expect("Elf-sections tag required");
|
||||
|
||||
// let bootloader_tag = boot_info.boot_loader_name_tag()
|
||||
// .expect("Elf-sections tag required");
|
||||
|
||||
// println!("bootloader: {}", bootloader_tag.name());
|
||||
// if command_line_tag.command_line().len() != 0 {
|
||||
// println!("command line: {}", command_line_tag.command_line());
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn acpi_info() -> Result<(), &'static str> {
|
||||
acpi::info()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Dump control registers
|
||||
pub fn regs() -> Result<(), &'static str> {
|
||||
use x86::registers::control::*;
|
||||
use x86::instructions::tables::tr;
|
||||
use x86::instructions::segmentation::*;
|
||||
use x86::registers::flags::*;
|
||||
use x86::structures::gdt;
|
||||
println!("cr0 = {:?}", Cr0::read());
|
||||
println!("cr3 = {:?}", Cr3::read());
|
||||
println!("cr4 = {:?}", Cr4::read());
|
||||
println!("flags= {:?}", flags());
|
||||
println!("tr = {:?}", tr());
|
||||
println!("ss = {:?}", ss());
|
||||
println!("cs = {:?}", cs());
|
||||
println!("ds = {:?}", ds());
|
||||
println!("es = {:?}", es());
|
||||
println!("fs = {:?}", fs());
|
||||
println!("gs = {:?}", gs());
|
||||
unsafe {
|
||||
println!(
|
||||
"tss = {:#?}",
|
||||
gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize])
|
||||
);
|
||||
}
|
||||
flush!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Dump cpu info, should add power management info
|
||||
pub fn cpu() -> Result<(), &'static str> {
|
||||
use arch::x86::devices::cpu;
|
||||
cpu::cpu_info().expect("cpu info not available");
|
||||
flush!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn int3() -> Result<(), &'static str> {
|
||||
use x86;
|
||||
x86::instructions::interrupts::int3();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unconditional_recursion)]
|
||||
pub fn overflow() -> Result<(), &'static str> {
|
||||
fn stack_overflow() {
|
||||
stack_overflow();
|
||||
}
|
||||
stack_overflow();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn page_fault() -> Result<(), &'static str> {
|
||||
unsafe {
|
||||
*(0xdead as *mut u32) = 42;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ pub fn kmain() -> ! {
|
|||
// unsafe VGA
|
||||
unsafe { console::CONSOLE.init(); }
|
||||
|
||||
pci::lspci();
|
||||
if let Ok(slot) = pci::get_ide1() {
|
||||
println!("found IDE at slot {}", slot);
|
||||
}
|
||||
// scheduler WIP
|
||||
// scheduling::schedule();
|
||||
unreachable!();
|
||||
|
|
|
|||
|
|
@ -101,3 +101,63 @@ pub fn init_noncore() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// for console
|
||||
#[allow(unconditional_recursion)]
|
||||
pub fn overflow() {
|
||||
overflow();
|
||||
}
|
||||
|
||||
/// for console
|
||||
pub fn page_fault() {
|
||||
unsafe {
|
||||
*(0xdead as *mut u32) = 42;
|
||||
};
|
||||
}
|
||||
|
||||
/// Print the kernel stack
|
||||
pub fn print_stack() {
|
||||
fn hexdump(start: usize, end: usize) {
|
||||
let mut address = 0;
|
||||
let data = unsafe { core::slice::from_raw_parts_mut(start as *mut u8, end - start) };
|
||||
while address <= data.len() {
|
||||
let next_end = core::cmp::min(address + 16, data.len());
|
||||
print_line(&data[address..next_end], address + start);
|
||||
address = address + 16;
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
|
||||
fn is_control(c: char) -> bool {
|
||||
!(c >= ' ' && c <= '~')
|
||||
}
|
||||
|
||||
fn print_line(line: &[u8], address: usize) {
|
||||
print!("\n{:#08x}: ", address);
|
||||
for byte in line {
|
||||
print!("{:02x} ", *byte);
|
||||
}
|
||||
let length: usize = 16 - line.len();
|
||||
for _ in 0..length {
|
||||
print!(" ");
|
||||
}
|
||||
print!("|");
|
||||
for byte in line {
|
||||
match is_control(*byte as char) {
|
||||
true => print!("."),
|
||||
false => print!("{}", *byte as char),
|
||||
};
|
||||
}
|
||||
print!("|");
|
||||
}
|
||||
|
||||
let esp: usize;
|
||||
let ebp: usize;
|
||||
unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) };
|
||||
println!("esp = {:#x}", esp);
|
||||
println!("ebp = {:#x}", ebp);
|
||||
println!("size = {:#X} bytes", ebp - esp);
|
||||
hexdump(esp, ebp);
|
||||
flush!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,79 @@
|
|||
// https://wiki.osdev.org/PCI
|
||||
|
||||
use x86::devices::io::{Pio};
|
||||
use x86::devices::io::{Pio, Io};
|
||||
|
||||
pub static mut PCI_CONFIG_ADDRESS: Pio<u8> = Pio::new(0xCF8);
|
||||
pub static mut PCI_CONFIG_DATA: Pio<u8> = Pio::new(0xCFC);
|
||||
pub static mut PCI_CONFIG_ADDRESS: Pio<u32> = Pio::new(0xCF8);
|
||||
pub static mut PCI_CONFIG_DATA: Pio<u32> = Pio::new(0xCFC);
|
||||
|
||||
pub fn get_ide1() -> Result<u32, ()> {
|
||||
let bus = 0;
|
||||
|
||||
for slot in 0..31 {
|
||||
let vendor = pci_config_read_word(bus, slot, 0, 0);
|
||||
if vendor == 0xffff {
|
||||
continue;
|
||||
}
|
||||
let class = pci_config_read_byte(bus, slot, 0, 11);
|
||||
let subclass = pci_config_read_byte(bus, slot, 0, 10);
|
||||
if class == 0x01 && subclass == 0x01 {
|
||||
return Ok(slot);
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn lspci() {
|
||||
pci_config_read_word(1, 1, 1, 2);
|
||||
let bus = 0;
|
||||
|
||||
for slot in 0..31 {
|
||||
let vendor = pci_config_read_word(bus, slot, 0, 0);
|
||||
if vendor == 0xffff {
|
||||
continue;
|
||||
}
|
||||
let header_type = pci_config_read_byte(bus, slot, 0, 14) ;
|
||||
if header_type & 0x80 != 0 {
|
||||
// device has multiple functions
|
||||
for function in 0..0x7 {
|
||||
let vendor = pci_config_read_word(bus, slot, function, 0);
|
||||
if vendor != 0xffff {
|
||||
pci_display(bus, slot, function);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pci_display(bus, slot, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pci_config_read_word(bus: u32, slot: u32, func: u32, offset: u32) {
|
||||
// let address: u64 = (bus as u32) << 16
|
||||
// | (slot as u32) << 11
|
||||
// | (func as u32) << 8
|
||||
// | (offset as u32) & 0xfc
|
||||
// | 0x80000000;
|
||||
let address: u64 = 0x80000000;
|
||||
println!("{} {} {} {}", bus, slot, func, offset);
|
||||
println!("{:#x}", address);
|
||||
println!("{:#b}", address);
|
||||
pub fn pci_display(bus: u32, slot: u32, function: u32) {
|
||||
let vendor = pci_config_read_word(bus, slot, function, 0);
|
||||
let device = pci_config_read_word(bus, slot, function, 2);
|
||||
let class = pci_config_read_byte(bus, slot, function, 11);
|
||||
let subclass = pci_config_read_byte(bus, slot, function, 10);
|
||||
println!("{}:{}.{} {:#x},{:#x}: {:#x} {:#x}",
|
||||
bus, slot, function, class, subclass, vendor, device);
|
||||
}
|
||||
|
||||
pub fn pci_access(bus: u32, slot: u32, func: u32, offset: u32) {
|
||||
let address = (bus as u32) << 16
|
||||
| (slot as u32) << 11
|
||||
| (func as u32) << 8
|
||||
| (offset as u32) & 0xfc
|
||||
| 0x80000000;
|
||||
unsafe { PCI_CONFIG_ADDRESS.write(address); }
|
||||
}
|
||||
|
||||
pub fn pci_config_read_doubleword(bus: u32, slot: u32, func: u32, offset: u32) -> u32 {
|
||||
pci_access(bus, slot, func, offset);
|
||||
unsafe { PCI_CONFIG_DATA.read() }
|
||||
}
|
||||
|
||||
pub fn pci_config_read_word(bus: u32, slot: u32, func: u32, offset: u32) -> u16 {
|
||||
pci_access(bus, slot, func, offset);
|
||||
unsafe { (PCI_CONFIG_DATA.read() >> ((offset & 2) * 8)) as u16 }
|
||||
}
|
||||
|
||||
pub fn pci_config_read_byte(bus: u32, slot: u32, func: u32, offset: u32) -> u8 {
|
||||
pci_access(bus, slot, func, offset);
|
||||
unsafe { (PCI_CONFIG_DATA.read() >> ((offset & 3) * 8)) as u8 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,3 +15,8 @@ pub fn realtime() -> (u32, u32) {
|
|||
let sum = start.1 + offset.1;
|
||||
(start.0 + offset.0 + sum / 1_000_000, sum % 1_000_000)
|
||||
}
|
||||
|
||||
pub fn uptime() {
|
||||
let mut offset = self::OFFSET.lock();
|
||||
println!("{}s", offset.0 + offset.1 / 1_000_000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ pub mod cursor;
|
|||
pub use self::color::{Color, ColorCode};
|
||||
use self::cursor::CURSOR;
|
||||
|
||||
use console;
|
||||
|
||||
pub static mut VGA: Writer = self::Writer::new();
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -16,6 +14,7 @@ struct ScreenChar {
|
|||
}
|
||||
|
||||
// print wrapper macro around vga
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ({
|
||||
$crate::vga::print(format_args!($($arg)*));
|
||||
|
|
@ -23,6 +22,7 @@ macro_rules! print {
|
|||
}
|
||||
|
||||
// flushed print
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! fprint {
|
||||
($($arg:tt)*) => ({
|
||||
print!($($arg)*);
|
||||
|
|
@ -31,12 +31,15 @@ macro_rules! fprint {
|
|||
}
|
||||
|
||||
// print with a line feed
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! println {
|
||||
() => ({print!("\n")});
|
||||
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
||||
}
|
||||
|
||||
// flushed println
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! fprintln {
|
||||
($($arg:tt)*) => ({
|
||||
println!($($arg)*);
|
||||
|
|
@ -73,8 +76,6 @@ pub struct Writer {
|
|||
pub buffer_pos: usize,
|
||||
pub color_code: ColorCode,
|
||||
buffer: [u8; BUFFER_ROWS * BUFFER_COLS],
|
||||
command: [u8; 10],
|
||||
command_len: usize,
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
|
|
@ -83,46 +84,36 @@ impl Writer {
|
|||
buffer_pos: 0,
|
||||
color_code: ColorCode::new(Color::White, Color::Black),
|
||||
buffer: [0; BUFFER_ROWS * BUFFER_COLS],
|
||||
command: [b'\0'; 10],
|
||||
command_len: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_command(&self) -> Result<&str, &'static str> {
|
||||
match core::str::from_utf8(&self.command) {
|
||||
Ok(y) => Ok(&y[..self.command_len]),
|
||||
Err(_) => Err("Command is not utf8 char"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn erase_byte(&mut self) {
|
||||
self.buffer_pos -= 2;
|
||||
let i = self.buffer_pos;
|
||||
self.buffer[i] = b' ';
|
||||
self.buffer[i + 1] = self.color_code.0;
|
||||
self.flush();
|
||||
// flush!();
|
||||
}
|
||||
|
||||
pub fn write_byte(&mut self, byte: u8) {
|
||||
let i = self.buffer_pos;
|
||||
|
||||
match byte {
|
||||
b'\n' => {
|
||||
let current_line = self.buffer_pos / (BUFFER_COLS);
|
||||
self.buffer_pos = (current_line + 1) * BUFFER_COLS;
|
||||
}
|
||||
byte => {
|
||||
self.buffer[i] = byte;
|
||||
self.buffer[i + 1] = self.color_code.0;
|
||||
self.buffer[self.buffer_pos] = byte;
|
||||
self.buffer[self.buffer_pos + 1] = self.color_code.0;
|
||||
self.buffer_pos += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if self.buffer_pos >= self.buffer.len() {
|
||||
self.scroll();
|
||||
self.flush();
|
||||
}
|
||||
// flushing here is correct but slow
|
||||
// self.flush();
|
||||
}
|
||||
|
||||
pub fn write_str(&mut self, s: &str) {
|
||||
|
|
@ -132,9 +123,7 @@ impl Writer {
|
|||
}
|
||||
|
||||
fn flush_cursor(&self) {
|
||||
unsafe {
|
||||
CURSOR.flush(self.buffer_pos / 2);
|
||||
}
|
||||
unsafe { CURSOR.flush(self.buffer_pos / 2); }
|
||||
}
|
||||
|
||||
pub fn flush(&mut self) {
|
||||
|
|
@ -157,7 +146,6 @@ impl Writer {
|
|||
self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] =
|
||||
ColorCode::new(Color::White, Color::Black).0;
|
||||
}
|
||||
|
||||
self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue