mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
121 lines
4.3 KiB
Rust
121 lines
4.3 KiB
Rust
//! The virtio of jinux
|
|
#![no_std]
|
|
#![forbid(unsafe_code)]
|
|
#![allow(dead_code)]
|
|
#![feature(fn_traits)]
|
|
|
|
extern crate alloc;
|
|
|
|
use component::init_component;
|
|
|
|
use alloc::boxed::Box;
|
|
use bitflags::bitflags;
|
|
use component::ComponentInitError;
|
|
use device::{
|
|
block::device::BlockDevice, console::device::ConsoleDevice, input::device::InputDevice,
|
|
network::device::NetworkDevice, VirtioDeviceType,
|
|
};
|
|
use log::{error, warn};
|
|
use transport::{mmio::VIRTIO_MMIO_DRIVER, pci::VIRTIO_PCI_DRIVER, DeviceStatus};
|
|
|
|
use crate::transport::VirtioTransport;
|
|
|
|
pub mod device;
|
|
pub mod queue;
|
|
mod transport;
|
|
|
|
#[init_component]
|
|
fn virtio_component_init() -> Result<(), ComponentInitError> {
|
|
// Find all devices and register them to the corresponding crate
|
|
transport::init();
|
|
while let Some(mut transport) = pop_device_transport() {
|
|
// Reset device
|
|
transport.set_device_status(DeviceStatus::empty()).unwrap();
|
|
// Set to acknowledge
|
|
transport
|
|
.set_device_status(DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER)
|
|
.unwrap();
|
|
// negotiate features
|
|
negotiate_features(&mut transport);
|
|
|
|
// change to features ok status
|
|
transport
|
|
.set_device_status(
|
|
DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER | DeviceStatus::FEATURES_OK,
|
|
)
|
|
.unwrap();
|
|
let device_type = transport.device_type();
|
|
let res = match transport.device_type() {
|
|
VirtioDeviceType::Block => BlockDevice::init(transport),
|
|
VirtioDeviceType::Input => InputDevice::init(transport),
|
|
VirtioDeviceType::Network => NetworkDevice::init(transport),
|
|
VirtioDeviceType::Console => ConsoleDevice::init(transport),
|
|
_ => {
|
|
warn!("[Virtio]: Found unimplemented device:{:?}", device_type);
|
|
Ok(())
|
|
}
|
|
};
|
|
if res.is_err() {
|
|
error!(
|
|
"[Virtio]: Device initialization error:{:?}, device type:{:?}",
|
|
res, device_type
|
|
);
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn pop_device_transport() -> Option<Box<dyn VirtioTransport>> {
|
|
if let Some(device) = VIRTIO_PCI_DRIVER.get().unwrap().pop_device_transport() {
|
|
return Some(Box::new(device));
|
|
}
|
|
if let Some(device) = VIRTIO_MMIO_DRIVER.get().unwrap().pop_device_transport() {
|
|
return Some(Box::new(device));
|
|
}
|
|
None
|
|
}
|
|
|
|
fn negotiate_features(transport: &mut Box<dyn VirtioTransport>) {
|
|
let features = transport.device_features();
|
|
let mask = ((1u64 << 24) - 1) | (((1u64 << 24) - 1) << 50);
|
|
let device_specified_features = features & mask;
|
|
let device_support_features = match transport.device_type() {
|
|
VirtioDeviceType::Network => NetworkDevice::negotiate_features(device_specified_features),
|
|
VirtioDeviceType::Block => BlockDevice::negotiate_features(device_specified_features),
|
|
VirtioDeviceType::Input => InputDevice::negotiate_features(device_specified_features),
|
|
VirtioDeviceType::Console => ConsoleDevice::negotiate_features(device_specified_features),
|
|
_ => device_specified_features,
|
|
};
|
|
let mut support_feature = Feature::from_bits_truncate(features);
|
|
support_feature.remove(Feature::RING_EVENT_IDX);
|
|
transport
|
|
.set_driver_features(features & (support_feature.bits | device_support_features))
|
|
.unwrap();
|
|
}
|
|
|
|
bitflags! {
|
|
/// all device features, bits 0~23 and 50~63 are sepecified by device.
|
|
/// if using this struct to translate u64, use from_bits_truncate function instead of from_bits
|
|
///
|
|
struct Feature: u64 {
|
|
|
|
// device independent
|
|
const NOTIFY_ON_EMPTY = 1 << 24; // legacy
|
|
const ANY_LAYOUT = 1 << 27; // legacy
|
|
const RING_INDIRECT_DESC = 1 << 28;
|
|
const RING_EVENT_IDX = 1 << 29;
|
|
const UNUSED = 1 << 30; // legacy
|
|
const VERSION_1 = 1 << 32; // detect legacy
|
|
|
|
// since virtio v1.1
|
|
const ACCESS_PLATFORM = 1 << 33;
|
|
const RING_PACKED = 1 << 34;
|
|
const IN_ORDER = 1 << 35;
|
|
const ORDER_PLATFORM = 1 << 36;
|
|
const SR_IOV = 1 << 37;
|
|
const NOTIFICATION_DATA = 1 << 38;
|
|
const NOTIF_CONFIG_DATA = 1 << 39;
|
|
const RING_RESET = 1 << 40;
|
|
}
|
|
}
|