mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-19 04:26:39 +00:00
Refactor project structure
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
bd878dd1c9
commit
e3c227ae06
121
kernel/comps/virtio/src/lib.rs
Normal file
121
kernel/comps/virtio/src/lib.rs
Normal file
@ -0,0 +1,121 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//! The virtio of Asterinas.
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![allow(dead_code)]
|
||||
#![feature(fn_traits)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use component::{init_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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user