forked from AbleOS/ableos
back into virtio work
This commit is contained in:
parent
a001a7e168
commit
08c2cf73ea
|
@ -18,17 +18,13 @@ run-args = [
|
|||
"-smp",
|
||||
"cores=2",
|
||||
|
||||
"-device",
|
||||
"cirrus-vga",
|
||||
|
||||
# "-device",
|
||||
# "virtio-blk-pci,drive=drive0,id=virtblk0,num-queues=4",
|
||||
# A simple example of a boot image
|
||||
# "-drive",
|
||||
# "file=disk.qcow2,if=none,id=drive0",
|
||||
|
||||
"-device",
|
||||
"virtio-rng",
|
||||
"-soundhw", "pcspk",
|
||||
"-device", "virtio-gpu-pci",
|
||||
|
||||
# "-machine", "pcspk-audiodev=0",
|
||||
|
||||
|
||||
"-qmp",
|
||||
"unix:../qmp-sock,server,nowait"
|
||||
|
|
|
@ -43,8 +43,7 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
|||
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
}
|
||||
|
||||
// This gives fast interrupts
|
||||
set_pit_frequency(1000);
|
||||
reset_pit_for_cpu();
|
||||
|
||||
idt[InterruptIndex::Timer.as_usize()].set_handler_fn(timer_interrupt_handler);
|
||||
idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler);
|
||||
|
@ -151,13 +150,29 @@ pub fn init_idt() {
|
|||
IDT.load();
|
||||
}
|
||||
|
||||
fn set_pit_frequency(freq: u32) {
|
||||
pub fn set_pit_frequency(pit: u16, freq: u32) {
|
||||
let divisor: u16 = (1193180 / freq).try_into().unwrap();
|
||||
|
||||
unsafe {
|
||||
outb(0x36, 0x43);
|
||||
|
||||
outb((divisor & 0xFF) as u8, 0x40);
|
||||
outb((divisor >> 8) as u8, 0x40);
|
||||
outb((divisor & 0xFF) as u8, 0x39 + pit);
|
||||
outb((divisor >> 8) as u8, 0x40 + pit);
|
||||
}
|
||||
}
|
||||
pub fn set_pit_1(freq: u32) {
|
||||
set_pit_frequency(1, freq);
|
||||
}
|
||||
pub fn set_pit_2(freq: u32) {
|
||||
set_pit_frequency(2, freq);
|
||||
}
|
||||
|
||||
pub fn set_pit_3(freq: u32) {
|
||||
set_pit_frequency(3, freq);
|
||||
}
|
||||
|
||||
pub fn reset_pit_for_cpu() {
|
||||
set_pit_1(1000);
|
||||
set_pit_2(1000);
|
||||
set_pit_3(1000);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
pub mod character_devs;
|
||||
pub mod id;
|
||||
pub mod pci_inner;
|
||||
|
||||
mod dev_vterm;
|
||||
|
||||
pub mod id;
|
||||
pub mod pci;
|
||||
pub mod pci_inner;
|
||||
|
||||
pub use self::Device::*;
|
||||
|
||||
use crate::devices::dev_vterm::VTerm;
|
||||
|
|
178
ableos/src/devices/pci/enums.rs
Normal file
178
ableos/src/devices/pci/enums.rs
Normal file
|
@ -0,0 +1,178 @@
|
|||
/// The major class specification for a PCI device.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(C)]
|
||||
pub enum PciClass {
|
||||
Unclassified = 0x00,
|
||||
MassStorage = 0x01,
|
||||
Network = 0x02,
|
||||
Display = 0x03,
|
||||
Multimedia = 0x04,
|
||||
Memory = 0x05,
|
||||
Bridge = 0x06,
|
||||
Other = 0xFF,
|
||||
}
|
||||
impl PciClass {
|
||||
/// Convert a u8 into the corresponding PciClass
|
||||
pub fn from_u8(n: u8) -> PciClass {
|
||||
match n {
|
||||
0x00 => PciClass::Unclassified,
|
||||
0x01 => PciClass::MassStorage,
|
||||
0x02 => PciClass::Network,
|
||||
0x03 => PciClass::Display,
|
||||
0x04 => PciClass::Multimedia,
|
||||
0x05 => PciClass::Memory,
|
||||
0x06 => PciClass::Bridge,
|
||||
_ => PciClass::Other,
|
||||
}
|
||||
}
|
||||
/// Convert a PciClass to its u8 representation
|
||||
pub fn as_u8(&self) -> u8 {
|
||||
*self as u8
|
||||
}
|
||||
}
|
||||
impl From<u8> for PciClass {
|
||||
/// Convert a u8 into the corresponding PciClass
|
||||
fn from(n: u8) -> Self {
|
||||
Self::from_u8(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(C)]
|
||||
/// Full class specification (type and subtype) for a PCI device.
|
||||
///
|
||||
/// Uses non-camel-case types for readability.
|
||||
pub enum PciFullClass {
|
||||
Unclassified_NonVgaCompatible = 0x0000,
|
||||
Unclassified_VgaCompatible = 0x0001,
|
||||
|
||||
MassStorage_ScsiBus = 0x0100,
|
||||
MassStorage_IDE = 0x0101,
|
||||
MassStorage_Floppy = 0x0102,
|
||||
MassStorage_IpiBus = 0x0103,
|
||||
MassStorage_RAID = 0x0104,
|
||||
MassStorage_ATA = 0x0105,
|
||||
MassStorage_SATA = 0x0106,
|
||||
MassStorage_SerialSCSI = 0x0107,
|
||||
MassStorage_NVM = 0x0108,
|
||||
MassStorage_Other = 0x0180,
|
||||
|
||||
Network_Ethernet = 0x0200,
|
||||
Network_TokenRing = 0x0201,
|
||||
Network_FDDI = 0x0202,
|
||||
Network_ATM = 0x0203,
|
||||
Network_ISDN = 0x0204,
|
||||
Network_WorldFlip = 0x0205,
|
||||
Network_PICMG = 0x0206,
|
||||
Network_Infiniband = 0x0207,
|
||||
Network_Fabric = 0x0208,
|
||||
Network_Other = 0x0280,
|
||||
|
||||
Display_VGA = 0x0300,
|
||||
Display_XGA = 0x0301,
|
||||
Display_3D = 0x0302,
|
||||
Display_Other = 0x0380,
|
||||
|
||||
Multimedia_Video = 0x0400,
|
||||
Multimedia_AudioController = 0x0401,
|
||||
Multimedia_Telephony = 0x0402,
|
||||
Multimedia_AudioDevice = 0x0403,
|
||||
Multimedia_Other = 0x0480,
|
||||
|
||||
Memory_RAM = 0x0500,
|
||||
Memory_Flash = 0x0501,
|
||||
Memory_Other = 0x0580,
|
||||
|
||||
Bridge_Host = 0x0600,
|
||||
Bridge_ISA = 0x0601,
|
||||
Bridge_EISA = 0x0602,
|
||||
Bridge_MCA = 0x0603,
|
||||
Bridge_PciToPci = 0x0604,
|
||||
Bridge_PCMCIA = 0x0605,
|
||||
Bridge_NuBus = 0x0606,
|
||||
Bridge_CardBus = 0x0607,
|
||||
Bridge_RACEway = 0x0608,
|
||||
Bridge_PciToPciSemiTransparent = 0x0609,
|
||||
Bridge_InfinibandToPci = 0x060A,
|
||||
Bridge_Other = 0x0680,
|
||||
|
||||
Unknown = 0xFFFF,
|
||||
}
|
||||
impl PciFullClass {
|
||||
// listen, i know this sucks, but i didn't want to include
|
||||
// `num`, `num-traits` and `num-derive` as dependencies for
|
||||
// this crate just for a convenience function
|
||||
/// Convert a u16 into the corresponding PciFullClass
|
||||
pub fn from_u16(n: u16) -> PciFullClass {
|
||||
match n {
|
||||
0x0000 => PciFullClass::Unclassified_NonVgaCompatible,
|
||||
0x0001 => PciFullClass::Unclassified_VgaCompatible,
|
||||
|
||||
0x0100 => PciFullClass::MassStorage_ScsiBus,
|
||||
0x0101 => PciFullClass::MassStorage_IDE,
|
||||
0x0102 => PciFullClass::MassStorage_Floppy,
|
||||
0x0103 => PciFullClass::MassStorage_IpiBus,
|
||||
0x0104 => PciFullClass::MassStorage_RAID,
|
||||
0x0105 => PciFullClass::MassStorage_ATA,
|
||||
0x0106 => PciFullClass::MassStorage_SATA,
|
||||
0x0107 => PciFullClass::MassStorage_SerialSCSI,
|
||||
0x0108 => PciFullClass::MassStorage_NVM,
|
||||
0x0180 => PciFullClass::MassStorage_Other,
|
||||
|
||||
0x0200 => PciFullClass::Network_Ethernet,
|
||||
0x0201 => PciFullClass::Network_TokenRing,
|
||||
0x0202 => PciFullClass::Network_FDDI,
|
||||
0x0203 => PciFullClass::Network_ATM,
|
||||
0x0204 => PciFullClass::Network_ISDN,
|
||||
0x0205 => PciFullClass::Network_WorldFlip,
|
||||
0x0206 => PciFullClass::Network_PICMG,
|
||||
0x0207 => PciFullClass::Network_Infiniband,
|
||||
0x0208 => PciFullClass::Network_Fabric,
|
||||
0x0280 => PciFullClass::Network_Other,
|
||||
|
||||
0x0300 => PciFullClass::Display_VGA,
|
||||
0x0301 => PciFullClass::Display_XGA,
|
||||
0x0302 => PciFullClass::Display_3D,
|
||||
0x0380 => PciFullClass::Display_Other,
|
||||
|
||||
0x0400 => PciFullClass::Multimedia_Video,
|
||||
0x0401 => PciFullClass::Multimedia_AudioController,
|
||||
0x0402 => PciFullClass::Multimedia_Telephony,
|
||||
0x0403 => PciFullClass::Multimedia_AudioDevice,
|
||||
0x0480 => PciFullClass::Multimedia_Other,
|
||||
|
||||
0x0500 => PciFullClass::Memory_RAM,
|
||||
0x0501 => PciFullClass::Memory_Flash,
|
||||
0x0580 => PciFullClass::Memory_Other,
|
||||
|
||||
0x0600 => PciFullClass::Bridge_Host,
|
||||
0x0601 => PciFullClass::Bridge_ISA,
|
||||
0x0602 => PciFullClass::Bridge_EISA,
|
||||
0x0603 => PciFullClass::Bridge_MCA,
|
||||
0x0604 => PciFullClass::Bridge_PciToPci,
|
||||
0x0605 => PciFullClass::Bridge_PCMCIA,
|
||||
0x0606 => PciFullClass::Bridge_NuBus,
|
||||
0x0607 => PciFullClass::Bridge_CardBus,
|
||||
0x0608 => PciFullClass::Bridge_RACEway,
|
||||
0x0609 => PciFullClass::Bridge_PciToPciSemiTransparent,
|
||||
0x060A => PciFullClass::Bridge_InfinibandToPci,
|
||||
0x0680 => PciFullClass::Bridge_Other,
|
||||
|
||||
_ => PciFullClass::Unknown,
|
||||
}
|
||||
}
|
||||
/// Convert a PciFullClass to its u16 representation
|
||||
pub fn as_u16(&self) -> u16 {
|
||||
*self as u16
|
||||
}
|
||||
}
|
||||
impl From<u16> for PciFullClass {
|
||||
/// Convert a u16 into the corresponding PciFullClass
|
||||
fn from(n: u16) -> Self {
|
||||
Self::from_u16(n)
|
||||
}
|
||||
}
|
227
ableos/src/devices/pci/mod.rs
Normal file
227
ableos/src/devices/pci/mod.rs
Normal file
|
@ -0,0 +1,227 @@
|
|||
// The MIT License (MIT)
|
||||
// Copyright (c) 2021 trashbyte
|
||||
// See LICENSE.txt for full license
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::{format, string::String, vec::Vec};
|
||||
use core::fmt::{Display, Error, Formatter};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
mod enums;
|
||||
pub use enums::*;
|
||||
|
||||
pub mod port;
|
||||
use port::*;
|
||||
|
||||
// PciDeviceInfo ///////////////////////////////////////////////////////////////
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
/// A struct containing info about a PCI device.
|
||||
pub struct PciDeviceInfo {
|
||||
pub device: u8,
|
||||
pub bus: u8,
|
||||
pub device_id: u16,
|
||||
pub vendor_id: u16,
|
||||
pub full_class: PciFullClass,
|
||||
pub header_type: u8,
|
||||
pub bars: [u32; 6],
|
||||
pub supported_fns: [bool; 8],
|
||||
pub interrupt_line: u8,
|
||||
pub interrupt_pin: u8,
|
||||
}
|
||||
impl PciDeviceInfo {
|
||||
/// Get the class of the PCI device as a PciClass
|
||||
pub fn class(&self) -> PciClass {
|
||||
PciClass::from_u8(((self.full_class.as_u16() >> 8) & 0xFF) as u8)
|
||||
}
|
||||
/// Get the full class of the PCI device as a PciFullClass
|
||||
pub fn subclass(&self) -> PciClass {
|
||||
PciClass::from_u8((self.full_class.as_u16() & 0xFF) as u8)
|
||||
}
|
||||
}
|
||||
impl Display for PciDeviceInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let vendor_name = name_for_vendor_id(self.vendor_id);
|
||||
writeln!(
|
||||
f,
|
||||
"Device {:X} | Bus {:X} | Vendor: {}",
|
||||
self.device, self.bus, vendor_name
|
||||
)?;
|
||||
writeln!(
|
||||
f,
|
||||
" Class: {:?} ({:#06X})",
|
||||
self.full_class,
|
||||
self.full_class.as_u16()
|
||||
)?;
|
||||
writeln!(f, " Header type: {:X}", self.header_type)?;
|
||||
write!(f, " Supported functions: 0")?;
|
||||
for (i, b) in self.supported_fns.iter().enumerate().skip(1) {
|
||||
if *b {
|
||||
write!(f, ", {}", i)?;
|
||||
}
|
||||
}
|
||||
writeln!(f)?;
|
||||
write!(f, " BARs: [ ")?;
|
||||
for i in self.bars.iter() {
|
||||
if *i == 0 {
|
||||
write!(f, "0x0 ")?;
|
||||
} else {
|
||||
write!(f, "{:#010X} ", i)?;
|
||||
}
|
||||
}
|
||||
writeln!(f, "]")?;
|
||||
writeln!(
|
||||
f,
|
||||
" Interrupt line / pin: {} / {}",
|
||||
self.interrupt_line, self.interrupt_pin
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Public functions ////////////////////////////////////////////////////////////
|
||||
|
||||
/// Converts a u16 vendor id into a human-readable name.
|
||||
pub fn name_for_vendor_id(vendor_id: u16) -> String {
|
||||
match vendor_id {
|
||||
0x8086 => "Intel Corp. (0x8086)".into(),
|
||||
0x1234 => "QEMU (0x1234)".into(),
|
||||
_ => format!("Unknown({:#06X})", vendor_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Brute force scans for devices 0-31 on buses 0-255.
|
||||
pub fn brute_force_scan() -> Vec<PciDeviceInfo> {
|
||||
let mut infos = Vec::new();
|
||||
for bus in 0u8..=255 {
|
||||
for device in 0u8..32 {
|
||||
if let Some(info) = check_device(bus, device) {
|
||||
infos.push(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
infos
|
||||
}
|
||||
|
||||
// Internal functions //////////////////////////////////////////////////////////
|
||||
|
||||
fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
||||
assert!(device < 32);
|
||||
let function = 0u8;
|
||||
|
||||
let (device_id, vendor_id) = get_ids(bus, device, function);
|
||||
if vendor_id == 0xFFFF {
|
||||
// Device doesn't exist
|
||||
return None;
|
||||
}
|
||||
|
||||
let class = unsafe { pci_config_read(bus, device, 0, 0x8) };
|
||||
let class = (class >> 16) & 0x0000FFFF;
|
||||
let pci_class = PciFullClass::from_u16(class as u16);
|
||||
let header_type = get_header_type(bus, device, function);
|
||||
|
||||
let mut supported_fns = [true, false, false, false, false, false, false, false];
|
||||
if (header_type & 0x80) != 0 {
|
||||
// It is a multi-function device, so check remaining functions
|
||||
for function in 0u8..8 {
|
||||
if get_ids(bus, device, function).1 != 0xFFFF {
|
||||
if check_function(bus, device, function) {
|
||||
supported_fns[function as usize] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut bars = [0, 0, 0, 0, 0, 0];
|
||||
unsafe {
|
||||
bars[0] = pci_config_read(bus, device, 0, 0x10);
|
||||
bars[1] = pci_config_read(bus, device, 0, 0x14);
|
||||
bars[2] = pci_config_read(bus, device, 0, 0x18);
|
||||
bars[3] = pci_config_read(bus, device, 0, 0x1C);
|
||||
bars[4] = pci_config_read(bus, device, 0, 0x20);
|
||||
bars[5] = pci_config_read(bus, device, 0, 0x24);
|
||||
}
|
||||
|
||||
let last_row = unsafe { pci_config_read(bus, device, 0, 0x3C) };
|
||||
|
||||
Some(PciDeviceInfo {
|
||||
device,
|
||||
bus,
|
||||
device_id,
|
||||
vendor_id,
|
||||
full_class: pci_class,
|
||||
header_type,
|
||||
bars,
|
||||
supported_fns,
|
||||
interrupt_line: (last_row & 0xFF) as u8,
|
||||
interrupt_pin: ((last_row >> 8) & 0xFF) as u8,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address =
|
||||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32;
|
||||
|
||||
// write address
|
||||
unsafe {
|
||||
Port::<u32>::new(0xCF8).write(address);
|
||||
}
|
||||
|
||||
// read data
|
||||
unsafe { Port::<u32>::new(0xCFC).read() }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address =
|
||||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xfc) | 0x80000000) as u32;
|
||||
|
||||
// write address
|
||||
unsafe {
|
||||
Port::<u32>::new(0xCF8).write(address);
|
||||
}
|
||||
|
||||
// write data
|
||||
unsafe {
|
||||
Port::<u32>::new(0xCFC).write(value);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_header_type(bus: u8, device: u8, function: u8) -> u8 {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
let res = unsafe { pci_config_read(bus, device, function, 0x0C) };
|
||||
((res >> 16) & 0xFF) as u8
|
||||
}
|
||||
|
||||
fn check_function(bus: u8, device: u8, function: u8) -> bool {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
get_ids(bus, device, function).1 != 0xFFFF
|
||||
}
|
||||
|
||||
fn get_ids(bus: u8, device: u8, function: u8) -> (u16, u16) {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
let res = unsafe { pci_config_read(bus, device, function, 0) };
|
||||
let dev_id = ((res >> 16) & 0xFFFF) as u16;
|
||||
let vnd_id = (res & 0xFFFF) as u16;
|
||||
(dev_id, vnd_id)
|
||||
}
|
72
ableos/src/devices/pci/port.rs
Normal file
72
ableos/src/devices/pci/port.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
use core::marker::PhantomData;
|
||||
|
||||
/// Trait for limiting [Port] to only being able to read/write u8/16/32.
|
||||
pub(crate) trait PortRW {
|
||||
/// Read a value (self) from the port
|
||||
unsafe fn read_port(port: u16) -> Self;
|
||||
/// Write a value (self) to the port
|
||||
unsafe fn write_port(port: u16, value: Self);
|
||||
}
|
||||
|
||||
// PortRW Implementations //////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl PortRW for u8 {
|
||||
unsafe fn read_port(port: u16) -> Self {
|
||||
let value: u8;
|
||||
asm!("in al, dx", out("al") value, in("dx") port, options(nomem, nostack, preserves_flags));
|
||||
value
|
||||
}
|
||||
|
||||
unsafe fn write_port(port: u16, value: Self) {
|
||||
asm!("out dx, al", in("dx") port, in("al") value, options(nomem, nostack, preserves_flags));
|
||||
}
|
||||
}
|
||||
|
||||
impl PortRW for u16 {
|
||||
unsafe fn read_port(port: u16) -> Self {
|
||||
let value: u16;
|
||||
asm!("in ax, dx", out("ax") value, in("dx") port, options(nomem, nostack, preserves_flags));
|
||||
value
|
||||
}
|
||||
|
||||
unsafe fn write_port(port: u16, value: Self) {
|
||||
asm!("out dx, ax", in("dx") port, in("ax") value, options(nomem, nostack, preserves_flags));
|
||||
}
|
||||
}
|
||||
|
||||
impl PortRW for u32 {
|
||||
unsafe fn read_port(port: u16) -> Self {
|
||||
let value: u32;
|
||||
asm!("in eax, dx", out("eax") value, in("dx") port, options(nomem, nostack, preserves_flags));
|
||||
value
|
||||
}
|
||||
|
||||
unsafe fn write_port(port: u16, value: Self) {
|
||||
asm!("out dx, eax", in("dx") port, in("eax") value, options(nomem, nostack, preserves_flags));
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple wrapper around the asm instructions needed to read/write I/O ports.
|
||||
pub(crate) struct Port<T: PortRW> {
|
||||
addr: u16,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
impl<T: PortRW> Port<T> {
|
||||
/// Create a new `Port` with the given address and data size
|
||||
pub(crate) fn new(addr: u16) -> Self {
|
||||
Self {
|
||||
addr,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a value from the port
|
||||
pub(crate) unsafe fn read(&self) -> T {
|
||||
T::read_port(self.addr)
|
||||
}
|
||||
|
||||
/// Write a value to the port
|
||||
pub(crate) unsafe fn write(&self, value: T) {
|
||||
T::write_port(self.addr, value);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
//!
|
||||
//!
|
||||
|
||||
#[repr(C)]
|
||||
pub enum Vendors {
|
||||
ThreeDfxInteractiveInc = 0x121a,
|
||||
ThreeDLabs = 0x3d3d,
|
||||
|
|
|
@ -34,10 +34,7 @@ impl log::Log for SimpleLogger {
|
|||
record.args()
|
||||
);
|
||||
// kprint!("{}", msg);
|
||||
// NOTE: This needs to be fixed before merge
|
||||
if KERNEL_CONF.logging.log_to_serial {
|
||||
// #[track_caller]
|
||||
|
||||
serial_println!(
|
||||
"[{}{}{}][{}{}{}] {}",
|
||||
color.0,
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use cpuio::{inb, inl, outb, outl};
|
||||
use cpuio::{inb, inl, inw, outb, outl, outw};
|
||||
|
||||
pub fn read32(reg: u16) -> u32 {
|
||||
unsafe { inl(reg) }
|
||||
}
|
||||
pub fn read16(reg: u16) -> u16 {
|
||||
unsafe { inw(reg) as u16 }
|
||||
}
|
||||
|
||||
pub fn read8(reg: u16) -> u8 {
|
||||
unsafe { inb(reg) }
|
||||
|
@ -12,6 +15,10 @@ pub fn write32(reg: u16, val: u32) {
|
|||
unsafe { outl(val, reg) }
|
||||
}
|
||||
|
||||
pub fn write16(reg: u16, val: u16) {
|
||||
unsafe { outw(val, reg) }
|
||||
}
|
||||
|
||||
pub fn write8(reg: u16, val: u8) {
|
||||
unsafe { outb(val, reg) }
|
||||
}
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
pub mod rust_2021;
|
||||
|
||||
pub use core::assert;
|
||||
pub use core::option::Option::Some;
|
||||
pub use core::option::*;
|
||||
|
|
|
@ -2,6 +2,7 @@ pub use crate::print::*;
|
|||
pub use crate::serial_print::*;
|
||||
pub use alloc::{boxed::Box, format, string::*, vec, vec::*};
|
||||
pub use core::arch::asm;
|
||||
|
||||
pub use core::prelude::rust_2021::*;
|
||||
pub use core::prelude::v1::*;
|
||||
pub use log::{debug, info, trace, warn};
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
use core::alloc::Layout;
|
||||
|
||||
use crate::arch::interrupts::{reset_pit_for_cpu, set_pit_2};
|
||||
use crate::devices::{pci, pci_inner};
|
||||
use crate::encoding::bin;
|
||||
use crate::port_io::{read32, read8, write8};
|
||||
use crate::rhai_shell::shell;
|
||||
use crate::wasm_jumploader::run_program;
|
||||
use acpi::{AcpiTables, PlatformInfo};
|
||||
use cpuio::outb;
|
||||
use genfs::Fs;
|
||||
|
||||
/// Experimental scratchpad for testing.
|
||||
|
@ -16,14 +20,33 @@ pub fn scratchpad() {
|
|||
foo: (None) -> (Num);
|
||||
}";
|
||||
let axel = axel::parse(axel_raw.to_string());
|
||||
|
||||
for node in axel {
|
||||
info!("{:?}", node);
|
||||
}
|
||||
|
||||
use crate::devices::pci::brute_force_scan;
|
||||
let infos = brute_force_scan();
|
||||
for device in infos {
|
||||
match device.vendor_id {
|
||||
0x1af4 => {
|
||||
info!("Found virtio device");
|
||||
use crate::virtio::device_handler;
|
||||
device_handler(device);
|
||||
}
|
||||
_ => {
|
||||
info!("Found unknown device");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sound(1000);
|
||||
// sound_off();
|
||||
|
||||
// acpi();
|
||||
real_shell();
|
||||
}
|
||||
|
||||
pub fn pci_fun() {}
|
||||
use crate::port_io::write16;
|
||||
|
||||
pub fn acpi() {
|
||||
let acpi_handler = AcpiStruct {};
|
||||
|
@ -176,3 +199,31 @@ pub fn command_parser(user: String, command: String) {
|
|||
|
||||
use crate::filesystem::FILE_SYSTEM;
|
||||
use genfs::OpenOptions;
|
||||
|
||||
pub fn sound(n_frequency: u32) {
|
||||
let div: u32;
|
||||
let tmp: u8;
|
||||
|
||||
div = 1193180 / n_frequency;
|
||||
unsafe {
|
||||
outb(0xb6, 0x43);
|
||||
|
||||
set_pit_2(div);
|
||||
|
||||
//And play the sound using the PC speaker
|
||||
tmp = inb(0x61);
|
||||
if tmp != (tmp | 3) {
|
||||
outb(tmp | 3, 0x61);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sound_off() {
|
||||
unsafe {
|
||||
let tmp = inb(0x61) & 0xFC;
|
||||
outb(tmp, 0x61)
|
||||
};
|
||||
reset_pit_for_cpu();
|
||||
}
|
||||
|
||||
use cpuio::inb;
|
||||
|
|
|
@ -9,6 +9,26 @@ pub struct VirtioDevice {
|
|||
status: VirtioDeviceStatus,
|
||||
}
|
||||
|
||||
use crate::devices::pci::PciDeviceInfo;
|
||||
|
||||
pub fn device_handler(device: PciDeviceInfo) {
|
||||
use crate::devices::pci::PciClass::*;
|
||||
match device.class() {
|
||||
// Unclassified => todo!(),
|
||||
// MassStorage => todo!(),
|
||||
// Network => todo!(),
|
||||
Display => {
|
||||
trace!("Display found");
|
||||
println!("{}", device.interrupt_pin);
|
||||
}
|
||||
// Multimedia => todo!(),
|
||||
// Memory => todo!(),
|
||||
// Bridge => todo!(),
|
||||
// Other => todo!(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum VirtioDeviceStatus {
|
||||
// Indicates that the guest OS has found the device and recognized it as a valid virtio device.
|
||||
|
@ -59,3 +79,16 @@ pub struct VirtioDeviceNotification {
|
|||
pub index: u32,
|
||||
pub value: u32,
|
||||
}
|
||||
|
||||
pub struct Vring {
|
||||
pub addr: u64,
|
||||
pub len: u32,
|
||||
pub flags: u16,
|
||||
pub next: u16,
|
||||
}
|
||||
|
||||
pub struct VringAvail {
|
||||
pub flags: u16,
|
||||
pub idx: u16,
|
||||
pub ring: [u16; 0xFFFF],
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ pub mod host_functions;
|
|||
|
||||
use crate::{filesystem::FILE_SYSTEM, wasm_jumploader::host_functions::HostExternals};
|
||||
use genfs::{Fs, OpenOptions};
|
||||
use wasmi::{ImportsBuilder, ModuleInstance};
|
||||
use wasmi::{
|
||||
ImportsBuilder, MemoryDescriptor, ModuleImportResolver, ModuleInstance, StackRecycler,
|
||||
};
|
||||
|
||||
pub fn interp() {
|
||||
trace!("Interpreting...");
|
||||
|
@ -101,17 +103,24 @@ pub fn interp() {
|
|||
pub fn run_program(program: Vec<u8>) {
|
||||
// Load wasm binary and prepare it for instantiation.
|
||||
let module = wasmi::Module::from_buffer(&program).expect("failed to load wasm");
|
||||
|
||||
trace!("Loaded wasm binary");
|
||||
let imports = ImportsBuilder::new().with_resolver("env", &host_functions::HostExternals {});
|
||||
trace!("Created imports");
|
||||
|
||||
// Instantiate a module with empty imports and
|
||||
// assert that there is no `start` function.
|
||||
let instance = ModuleInstance::new(&module, &imports); // .expect("failed to instantiate wasm module")
|
||||
let instance = ModuleInstance::new(&module, &imports);
|
||||
|
||||
// .expect("failed to instantiate wasm module")
|
||||
|
||||
use wasmi::GlobalRef;
|
||||
match instance {
|
||||
Ok(inst) => {
|
||||
let instance = inst.assert_no_start();
|
||||
let mut instance = inst.assert_no_start();
|
||||
|
||||
let abc = instance.globals().capacity();
|
||||
|
||||
let mut is_driver = false;
|
||||
let _is_program = false;
|
||||
let mut has_driver_entry = false;
|
||||
|
|
Loading…
Reference in a new issue