From 08c2cf73ea326f2977401be7fd3517ae5d0af57a Mon Sep 17 00:00:00 2001 From: Able Date: Mon, 25 Apr 2022 13:39:39 -0500 Subject: [PATCH] back into virtio work --- ableos/Cargo.toml | 16 +- ableos/src/arch/x86_64/interrupts.rs | 25 ++- ableos/src/devices/mod.rs | 7 +- ableos/src/devices/pci/enums.rs | 178 +++++++++++++++++++++ ableos/src/devices/pci/mod.rs | 227 +++++++++++++++++++++++++++ ableos/src/devices/pci/port.rs | 72 +++++++++ ableos/src/devices/pci_inner.rs | 1 + ableos/src/logger.rs | 3 - ableos/src/port_io.rs | 9 +- ableos/src/prelude/mod.rs | 4 + ableos/src/prelude/rust_2021.rs | 1 + ableos/src/scratchpad.rs | 55 ++++++- ableos/src/virtio/mod.rs | 33 ++++ ableos/src/wasm_jumploader/mod.rs | 15 +- 14 files changed, 619 insertions(+), 27 deletions(-) create mode 100644 ableos/src/devices/pci/enums.rs create mode 100644 ableos/src/devices/pci/mod.rs create mode 100644 ableos/src/devices/pci/port.rs diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 8984597..d1d461a 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -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" diff --git a/ableos/src/arch/x86_64/interrupts.rs b/ableos/src/arch/x86_64/interrupts.rs index fd31b7f..ad601ec 100644 --- a/ableos/src/arch/x86_64/interrupts.rs +++ b/ableos/src/arch/x86_64/interrupts.rs @@ -43,8 +43,7 @@ static IDT: Lazy = 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); +} diff --git a/ableos/src/devices/mod.rs b/ableos/src/devices/mod.rs index d97c8df..2e618d0 100644 --- a/ableos/src/devices/mod.rs +++ b/ableos/src/devices/mod.rs @@ -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; diff --git a/ableos/src/devices/pci/enums.rs b/ableos/src/devices/pci/enums.rs new file mode 100644 index 0000000..f238bc8 --- /dev/null +++ b/ableos/src/devices/pci/enums.rs @@ -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 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 for PciFullClass { + /// Convert a u16 into the corresponding PciFullClass + fn from(n: u16) -> Self { + Self::from_u16(n) + } +} diff --git a/ableos/src/devices/pci/mod.rs b/ableos/src/devices/pci/mod.rs new file mode 100644 index 0000000..9a383bb --- /dev/null +++ b/ableos/src/devices/pci/mod.rs @@ -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 { + 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 { + 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::::new(0xCF8).write(address); + } + + // read data + unsafe { Port::::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::::new(0xCF8).write(address); + } + + // write data + unsafe { + Port::::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) +} diff --git a/ableos/src/devices/pci/port.rs b/ableos/src/devices/pci/port.rs new file mode 100644 index 0000000..e22b107 --- /dev/null +++ b/ableos/src/devices/pci/port.rs @@ -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 { + addr: u16, + _phantom: PhantomData, +} +impl Port { + /// 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); + } +} diff --git a/ableos/src/devices/pci_inner.rs b/ableos/src/devices/pci_inner.rs index 3884885..83cff97 100644 --- a/ableos/src/devices/pci_inner.rs +++ b/ableos/src/devices/pci_inner.rs @@ -2,6 +2,7 @@ //! //! +#[repr(C)] pub enum Vendors { ThreeDfxInteractiveInc = 0x121a, ThreeDLabs = 0x3d3d, diff --git a/ableos/src/logger.rs b/ableos/src/logger.rs index a42b0f8..8b7af29 100644 --- a/ableos/src/logger.rs +++ b/ableos/src/logger.rs @@ -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, diff --git a/ableos/src/port_io.rs b/ableos/src/port_io.rs index ad5fcc6..95bb1a2 100644 --- a/ableos/src/port_io.rs +++ b/ableos/src/port_io.rs @@ -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) } } diff --git a/ableos/src/prelude/mod.rs b/ableos/src/prelude/mod.rs index 77dad8e..9d3a594 100644 --- a/ableos/src/prelude/mod.rs +++ b/ableos/src/prelude/mod.rs @@ -1 +1,5 @@ pub mod rust_2021; + +pub use core::assert; +pub use core::option::Option::Some; +pub use core::option::*; diff --git a/ableos/src/prelude/rust_2021.rs b/ableos/src/prelude/rust_2021.rs index 1bfe654..114d92e 100644 --- a/ableos/src/prelude/rust_2021.rs +++ b/ableos/src/prelude/rust_2021.rs @@ -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}; diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs index 2164634..eca0498 100644 --- a/ableos/src/scratchpad.rs +++ b/ableos/src/scratchpad.rs @@ -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; diff --git a/ableos/src/virtio/mod.rs b/ableos/src/virtio/mod.rs index 6506e9e..b75f160 100644 --- a/ableos/src/virtio/mod.rs +++ b/ableos/src/virtio/mod.rs @@ -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], +} diff --git a/ableos/src/wasm_jumploader/mod.rs b/ableos/src/wasm_jumploader/mod.rs index 00dcff3..c4f6fc8 100644 --- a/ableos/src/wasm_jumploader/mod.rs +++ b/ableos/src/wasm_jumploader/mod.rs @@ -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) { // 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;