pci, ide stuff
This commit is contained in:
parent
c9ad4e9e58
commit
3d167f26d5
10 changed files with 115 additions and 73 deletions
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
extern crate core;
|
||||
|
||||
use console;
|
||||
use x86::devices::io::{Io, Pio};
|
||||
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
|
|
|
|||
4
kernel-rs/src/pci/ide.rs
Normal file
4
kernel-rs/src/pci/ide.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
use super::*;
|
||||
|
||||
pub fn init(drive: Pci) {
|
||||
}
|
||||
|
|
@ -1,58 +1,105 @@
|
|||
// https://wiki.osdev.org/PCI
|
||||
|
||||
use x86::devices::io::{Pio, Io};
|
||||
use alloc::vec::*;
|
||||
|
||||
pub mod ide;
|
||||
|
||||
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 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() {
|
||||
for pci in self::get_all() {
|
||||
println!("{}", pci);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all() -> Vec<Pci> {
|
||||
let bus = 0;
|
||||
let mut slot = 0;
|
||||
let mut pcis: Vec<Pci> = Vec::new();
|
||||
|
||||
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 {
|
||||
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
|
||||
for function in 0..0x7 {
|
||||
let vendor = pci_config_read_word(bus, slot, function, 0);
|
||||
if vendor != 0xffff {
|
||||
pci_display(bus, slot, function);
|
||||
pcis.push(pci);
|
||||
func += 1;
|
||||
if func == 7 {break;}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pci_display(bus, slot, 0);
|
||||
pcis.push(pci);
|
||||
slot += 1;
|
||||
if slot == 32 {break;}
|
||||
}
|
||||
pcis
|
||||
}
|
||||
|
||||
pub fn get_first(class: u8, subclass: u8) -> Option<Pci> {
|
||||
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<Pci> {
|
||||
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);
|
||||
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_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
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue