From 3d167f26d5a0f0c68ef2b3a0f63c3f02713d8a26 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 2 Feb 2019 18:46:41 +0100 Subject: [PATCH] pci, ide stuff --- kernel-rs/mk/qemu.mk | 3 +- kernel-rs/src/acpi/mod.rs | 22 ++--- kernel-rs/src/console.rs | 6 +- kernel-rs/src/keyboard.rs | 2 - kernel-rs/src/lib.rs | 12 ++- kernel-rs/src/pci/ide.rs | 4 + kernel-rs/src/pci/mod.rs | 131 ++++++++++++++++++++---------- kernel-rs/src/scheduling/sleep.rs | 2 +- kernel-rs/src/time.rs | 2 +- kernel-rs/src/vga/mod.rs | 4 +- 10 files changed, 115 insertions(+), 73 deletions(-) create mode 100644 kernel-rs/src/pci/ide.rs diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 99fbe143..014477be 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -9,7 +9,8 @@ qemu: -enable-kvm\ -curses\ -gdb tcp::$(QEMU_GDB_PORT)\ - -monitor unix:${QEMU_SOCKET},server,nowait + -monitor unix:${QEMU_SOCKET},server,nowait\ + -drive file=disk,if=ide,index=1 qemu-gdb: gdb\ diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 6a2f1f4b..58882099 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -128,33 +128,27 @@ impl Iterator for ACPISDTIter { /// Initalized the ACPI module pub fn init() -> Result<(), &'static str> { - if unsafe{ACPI.valid} { - return Ok(()); - } + if unsafe{ACPI.valid} { return Ok(()); } unsafe { ACPI.init() } } /// Load the ACPI module, addr given is a ptr to RSDP pub fn load(rsdp_addr: u32) -> Result<(), &'static str> { - if unsafe{ACPI.valid} { - return Ok(()); - } + if unsafe{!ACPI.valid} { return Ok(()); } unsafe { ACPI.load(rsdp_addr) } } /// Proceed to ACPI shutdown /// This function doesn't work with Virtual Box yet pub fn shutdown() { - if unsafe{ACPI.valid} { return } - dsdt::shutdown(fadt::get_controlblock().unwrap()); + if unsafe{!ACPI.valid} { return; } + dsdt::shutdown(fadt::get_controlblock().unwrap()).unwrap(); } /// Proceed to ACPI reboot /// This function need ACPI in v2 pub fn reboot() { - if unsafe {!ACPI.valid} { - println!("ACPI not initialized"); - } + if unsafe {!ACPI.valid} { println!("ACPI not initialized"); } if unsafe { ACPI.v2 } { fadt::reboot().unwrap() } else { @@ -166,8 +160,8 @@ pub fn reboot() { 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") + Ok(true) => println!("ACPI is disabled"), + Ok(false) => println!("ACPI is disabled"), + Err(msg) => println!("error while checking ACPI: {}", msg) } } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index f5c00bca..fa6b5fa5 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,6 +1,3 @@ -extern crate core; -// extern crate multiboot2; - use vga::*; use alloc::collections::BTreeMap; @@ -29,7 +26,6 @@ lazy_static! { 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()); @@ -39,7 +35,7 @@ lazy_static! { fn help() { println!("The following commands are available:"); - for (key, val) in COMMANDS.iter() { + for (key, _val) in COMMANDS.iter() { println!("{}", key); } } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index ec4e8766..75787813 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,5 +1,3 @@ -extern crate core; - use console; use x86::devices::io::{Io, Pio}; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index a9ebbbb9..c363c8a5 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -15,6 +15,7 @@ // x86 specific #![feature(abi_x86_interrupt)] +// extern crate core; extern crate alloc; #[macro_use] extern crate lazy_static; @@ -39,11 +40,12 @@ pub mod memory; pub mod arch; pub use arch::x86::consts::*; pub mod scheduling; +#[allow(dead_code)] pub mod time; pub mod pci; -/// kernel entry point. arch module is responsible for -/// calling this once the core has loaded +/// kernel entry point. +/// ::arch is responsible for calling this once the core has loaded. pub fn kmain() -> ! { // memory init after heap is available // memory::init_noncore(); @@ -51,9 +53,11 @@ pub fn kmain() -> ! { // unsafe VGA unsafe { console::CONSOLE.init(); } - if let Ok(slot) = pci::get_ide1() { - println!("found IDE at slot {}", slot); + if let Some(ide) = pci::get_first(0x1, 0x1) { + println!("found IDE at slot {}", ide.slot); + pci::ide::init(ide); } + // scheduler WIP // scheduling::schedule(); unreachable!(); diff --git a/kernel-rs/src/pci/ide.rs b/kernel-rs/src/pci/ide.rs new file mode 100644 index 00000000..f817db3e --- /dev/null +++ b/kernel-rs/src/pci/ide.rs @@ -0,0 +1,4 @@ +use super::*; + +pub fn init(drive: Pci) { +} diff --git a/kernel-rs/src/pci/mod.rs b/kernel-rs/src/pci/mod.rs index 827ffb77..20652210 100644 --- a/kernel-rs/src/pci/mod.rs +++ b/kernel-rs/src/pci/mod.rs @@ -1,59 +1,106 @@ // https://wiki.osdev.org/PCI - use x86::devices::io::{Pio, Io}; +use alloc::vec::*; + +pub mod ide; pub static mut PCI_CONFIG_ADDRESS: Pio = Pio::new(0xCF8); pub static mut PCI_CONFIG_DATA: Pio = Pio::new(0xCFC); -pub fn get_ide1() -> Result { - 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 struct Pci { + pub bus: u32, + pub slot: u32, + pub func: u32, + pub device: u16, + pub vendor: u16, + pub class: u8, + pub subclass: u8, + pub header_type: u8, } pub fn lspci() { - 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); - } + for pci in self::get_all() { + println!("{}", pci); } } -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 get_all() -> Vec { + let bus = 0; + let mut slot = 0; + let mut pcis: Vec = Vec::new(); + + while let Some(pci)= pci_get(bus, slot, 0) { + if pci.header_type & 0x80 != 0 { + let mut func = 0; + while let Some(pci)= pci_get(bus, slot, func) { + // device has multiple functions + pcis.push(pci); + func += 1; + if func == 7 {break;} + } + } + pcis.push(pci); + slot += 1; + if slot == 32 {break;} + } + pcis } +pub fn get_first(class: u8, subclass: u8) -> Option { + let bus = 0; + let mut slot = 0; + + while let Some(pci)= pci_get(bus, slot, 0) { + if pci.class == class && pci.subclass == subclass { + return Some(pci); + } + if pci.header_type & 0x80 != 0 { + let mut func = 0; + while let Some(pci)= pci_get(bus, slot, func) { + // device has multiple functions + if pci.class == class && pci.subclass == subclass { + return Some(pci); + } + func += 1; + if func == 7 {break;} + } + } + slot += 1; + if slot == 32 {break;} + } + None +} + +pub fn pci_get(bus: u32, slot: u32, func: u32) -> Option { + let vendor = pci_config_read_word(bus, slot, func, 0); + if vendor == 0xffff { return None } + let pci = Pci {bus, slot, func, vendor, + device: pci_config_read_word(bus, slot, func, 2), + subclass: pci_config_read_byte(bus, slot, func, 10), + class: pci_config_read_byte(bus, slot, func, 11), + header_type: pci_config_read_byte(bus, slot, func, 14), + }; + Some(pci) +} + +use core::fmt; +impl fmt::Display for Pci { + fn fmt(&self, f: &mut core::fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}.{} {:#x},{:#x} {:#x} {:#x}", + self.bus, self.slot, self.func, + self.class, self.subclass, + self.vendor, self.device); + Ok(()) + } +} + +// 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); +// 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 diff --git a/kernel-rs/src/scheduling/sleep.rs b/kernel-rs/src/scheduling/sleep.rs index af69d146..ca453133 100644 --- a/kernel-rs/src/scheduling/sleep.rs +++ b/kernel-rs/src/scheduling/sleep.rs @@ -3,7 +3,7 @@ //! way the scheduling algorithms don't have to worry about //! managing these //! -//! inspired from https://wiki.osdev.org/Blocking_Process +//! https://wiki.osdev.org/Blocking_Process use alloc::collections::vec_deque::VecDeque; use super::*; diff --git a/kernel-rs/src/time.rs b/kernel-rs/src/time.rs index 0d29eecf..ce8cc0aa 100644 --- a/kernel-rs/src/time.rs +++ b/kernel-rs/src/time.rs @@ -17,6 +17,6 @@ pub fn realtime() -> (u32, u32) { } pub fn uptime() { - let mut offset = self::OFFSET.lock(); + let offset = self::OFFSET.lock(); println!("{}s", offset.0 + offset.1 / 1_000_000); } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index e4ded8b6..2d8834ab 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -67,8 +67,6 @@ pub fn print(args: fmt::Arguments) { } } -extern crate core; - const BUFFER_ROWS: usize = 25; const BUFFER_COLS: usize = 80 * 2; @@ -153,7 +151,7 @@ impl Writer { // trait needed by formatting macros use core::fmt; impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { + fn write_str(&mut self, s: &str) -> fmt::Result { for byte in s.bytes() { self.write_byte(byte) }