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\
|
-enable-kvm\
|
||||||
-curses\
|
-curses\
|
||||||
-gdb tcp::$(QEMU_GDB_PORT)\
|
-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:
|
qemu-gdb:
|
||||||
gdb\
|
gdb\
|
||||||
|
|
|
||||||
|
|
@ -128,33 +128,27 @@ impl Iterator for ACPISDTIter {
|
||||||
|
|
||||||
/// Initalized the ACPI module
|
/// Initalized the ACPI module
|
||||||
pub fn init() -> Result<(), &'static str> {
|
pub fn init() -> Result<(), &'static str> {
|
||||||
if unsafe{ACPI.valid} {
|
if unsafe{ACPI.valid} { return Ok(()); }
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
unsafe { ACPI.init() }
|
unsafe { ACPI.init() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load the ACPI module, addr given is a ptr to RSDP
|
/// Load the ACPI module, addr given is a ptr to RSDP
|
||||||
pub fn load(rsdp_addr: u32) -> Result<(), &'static str> {
|
pub fn load(rsdp_addr: u32) -> Result<(), &'static str> {
|
||||||
if unsafe{ACPI.valid} {
|
if unsafe{!ACPI.valid} { return Ok(()); }
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
unsafe { ACPI.load(rsdp_addr) }
|
unsafe { ACPI.load(rsdp_addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proceed to ACPI shutdown
|
/// Proceed to ACPI shutdown
|
||||||
/// This function doesn't work with Virtual Box yet
|
/// This function doesn't work with Virtual Box yet
|
||||||
pub fn shutdown() {
|
pub fn shutdown() {
|
||||||
if unsafe{ACPI.valid} { return }
|
if unsafe{!ACPI.valid} { return; }
|
||||||
dsdt::shutdown(fadt::get_controlblock().unwrap());
|
dsdt::shutdown(fadt::get_controlblock().unwrap()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proceed to ACPI reboot
|
/// Proceed to ACPI reboot
|
||||||
/// This function need ACPI in v2
|
/// This function need ACPI in v2
|
||||||
pub fn reboot() {
|
pub fn reboot() {
|
||||||
if unsafe {!ACPI.valid} {
|
if unsafe {!ACPI.valid} { println!("ACPI not initialized"); }
|
||||||
println!("ACPI not initialized");
|
|
||||||
}
|
|
||||||
if unsafe { ACPI.v2 } {
|
if unsafe { ACPI.v2 } {
|
||||||
fadt::reboot().unwrap()
|
fadt::reboot().unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -166,8 +160,8 @@ pub fn reboot() {
|
||||||
pub fn info() {
|
pub fn info() {
|
||||||
if unsafe { !ACPI.valid } { println!("ACPI not initialized"); return }
|
if unsafe { !ACPI.valid } { println!("ACPI not initialized"); return }
|
||||||
match fadt::is_enable() {
|
match fadt::is_enable() {
|
||||||
Ok(True) => println!("ACPI is disabled"),
|
Ok(true) => println!("ACPI is disabled"),
|
||||||
Ok(False) => println!("ACPI is disabled"),
|
Ok(false) => println!("ACPI is disabled"),
|
||||||
Err(msg) => println!("error while checking ACPI")
|
Err(msg) => println!("error while checking ACPI: {}", msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
extern crate core;
|
|
||||||
// extern crate multiboot2;
|
|
||||||
|
|
||||||
use vga::*;
|
use vga::*;
|
||||||
use alloc::collections::BTreeMap;
|
use alloc::collections::BTreeMap;
|
||||||
|
|
||||||
|
|
@ -29,7 +26,6 @@ lazy_static! {
|
||||||
commands.insert("stack", ::memory::print_stack as fn());
|
commands.insert("stack", ::memory::print_stack as fn());
|
||||||
commands.insert("page_fault", ::memory::page_fault 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());
|
||||||
commands.insert("overflow", ::memory::overflow as fn());
|
|
||||||
|
|
||||||
//pci
|
//pci
|
||||||
commands.insert("lspci", ::pci::lspci as fn());
|
commands.insert("lspci", ::pci::lspci as fn());
|
||||||
|
|
@ -39,7 +35,7 @@ lazy_static! {
|
||||||
|
|
||||||
fn help() {
|
fn help() {
|
||||||
println!("The following commands are available:");
|
println!("The following commands are available:");
|
||||||
for (key, val) in COMMANDS.iter() {
|
for (key, _val) in COMMANDS.iter() {
|
||||||
println!("{}", key);
|
println!("{}", key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
extern crate core;
|
|
||||||
|
|
||||||
use console;
|
use console;
|
||||||
use x86::devices::io::{Io, Pio};
|
use x86::devices::io::{Io, Pio};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
// x86 specific
|
// x86 specific
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
|
|
||||||
|
// extern crate core;
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
@ -39,11 +40,12 @@ pub mod memory;
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub use arch::x86::consts::*;
|
pub use arch::x86::consts::*;
|
||||||
pub mod scheduling;
|
pub mod scheduling;
|
||||||
|
#[allow(dead_code)]
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod pci;
|
pub mod pci;
|
||||||
|
|
||||||
/// kernel entry point. arch module is responsible for
|
/// kernel entry point.
|
||||||
/// calling this once the core has loaded
|
/// ::arch is responsible for calling this once the core has loaded.
|
||||||
pub fn kmain() -> ! {
|
pub fn kmain() -> ! {
|
||||||
// memory init after heap is available
|
// memory init after heap is available
|
||||||
// memory::init_noncore();
|
// memory::init_noncore();
|
||||||
|
|
@ -51,9 +53,11 @@ pub fn kmain() -> ! {
|
||||||
// unsafe VGA
|
// unsafe VGA
|
||||||
unsafe { console::CONSOLE.init(); }
|
unsafe { console::CONSOLE.init(); }
|
||||||
|
|
||||||
if let Ok(slot) = pci::get_ide1() {
|
if let Some(ide) = pci::get_first(0x1, 0x1) {
|
||||||
println!("found IDE at slot {}", slot);
|
println!("found IDE at slot {}", ide.slot);
|
||||||
|
pci::ide::init(ide);
|
||||||
}
|
}
|
||||||
|
|
||||||
// scheduler WIP
|
// scheduler WIP
|
||||||
// scheduling::schedule();
|
// scheduling::schedule();
|
||||||
unreachable!();
|
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,59 +1,106 @@
|
||||||
// https://wiki.osdev.org/PCI
|
// https://wiki.osdev.org/PCI
|
||||||
|
|
||||||
use x86::devices::io::{Pio, Io};
|
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_ADDRESS: Pio<u32> = Pio::new(0xCF8);
|
||||||
pub static mut PCI_CONFIG_DATA: Pio<u32> = Pio::new(0xCFC);
|
pub static mut PCI_CONFIG_DATA: Pio<u32> = Pio::new(0xCFC);
|
||||||
|
|
||||||
pub fn get_ide1() -> Result<u32, ()> {
|
pub struct Pci {
|
||||||
let bus = 0;
|
pub bus: u32,
|
||||||
|
pub slot: u32,
|
||||||
for slot in 0..31 {
|
pub func: u32,
|
||||||
let vendor = pci_config_read_word(bus, slot, 0, 0);
|
pub device: u16,
|
||||||
if vendor == 0xffff {
|
pub vendor: u16,
|
||||||
continue;
|
pub class: u8,
|
||||||
}
|
pub subclass: u8,
|
||||||
let class = pci_config_read_byte(bus, slot, 0, 11);
|
pub header_type: u8,
|
||||||
let subclass = pci_config_read_byte(bus, slot, 0, 10);
|
|
||||||
if class == 0x01 && subclass == 0x01 {
|
|
||||||
return Ok(slot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lspci() {
|
pub fn lspci() {
|
||||||
let bus = 0;
|
for pci in self::get_all() {
|
||||||
|
println!("{}", pci);
|
||||||
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_display(bus: u32, slot: u32, function: u32) {
|
pub fn get_all() -> Vec<Pci> {
|
||||||
let vendor = pci_config_read_word(bus, slot, function, 0);
|
let bus = 0;
|
||||||
let device = pci_config_read_word(bus, slot, function, 2);
|
let mut slot = 0;
|
||||||
let class = pci_config_read_byte(bus, slot, function, 11);
|
let mut pcis: Vec<Pci> = Vec::new();
|
||||||
let subclass = pci_config_read_byte(bus, slot, function, 10);
|
|
||||||
println!("{}:{}.{} {:#x},{:#x}: {:#x} {:#x}",
|
while let Some(pci)= pci_get(bus, slot, 0) {
|
||||||
bus, slot, function, class, subclass, vendor, device);
|
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<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);
|
||||||
|
// println!("{}:{}.{} {:#x},{:#x}: {:#x} {:#x}",
|
||||||
|
// bus, slot, function, class, subclass, vendor, device);
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn pci_access(bus: u32, slot: u32, func: u32, offset: u32) {
|
pub fn pci_access(bus: u32, slot: u32, func: u32, offset: u32) {
|
||||||
let address = (bus as u32) << 16
|
let address = (bus as u32) << 16
|
||||||
| (slot as u32) << 11
|
| (slot as u32) << 11
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
//! way the scheduling algorithms don't have to worry about
|
//! way the scheduling algorithms don't have to worry about
|
||||||
//! managing these
|
//! managing these
|
||||||
//!
|
//!
|
||||||
//! inspired from https://wiki.osdev.org/Blocking_Process
|
//! https://wiki.osdev.org/Blocking_Process
|
||||||
|
|
||||||
use alloc::collections::vec_deque::VecDeque;
|
use alloc::collections::vec_deque::VecDeque;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,6 @@ pub fn realtime() -> (u32, u32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uptime() {
|
pub fn uptime() {
|
||||||
let mut offset = self::OFFSET.lock();
|
let offset = self::OFFSET.lock();
|
||||||
println!("{}s", offset.0 + offset.1 / 1_000_000);
|
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_ROWS: usize = 25;
|
||||||
const BUFFER_COLS: usize = 80 * 2;
|
const BUFFER_COLS: usize = 80 * 2;
|
||||||
|
|
||||||
|
|
@ -153,7 +151,7 @@ impl Writer {
|
||||||
// trait needed by formatting macros
|
// trait needed by formatting macros
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
impl fmt::Write for Writer {
|
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() {
|
for byte in s.bytes() {
|
||||||
self.write_byte(byte)
|
self.write_byte(byte)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue