Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions src/device/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,36 @@ use bitflags::bitflags;

bitflags! {
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub(crate) struct Feature: u64 {
// device independent
const NOTIFY_ON_EMPTY = 1 << 24; // legacy
const ANY_LAYOUT = 1 << 27; // legacy
/// The features supported by the virtio device.
pub struct Feature: u64 {
/// Mount the shared directory using the mount_tag method.
const VIRTIO_9P_F_MOUNT_TAG = 1 << 0;

/// device independent: notifies when the queue is empty.
const NOTIFY_ON_EMPTY = 1 << 24;
/// device independent: allows any layout for the queue.
const ANY_LAYOUT = 1 << 27;
/// device independent: Supports indirect descriptors in the virtio ring.
const RING_INDIRECT_DESC = 1 << 28;
/// device independent: Supports event index feature in the virtio ring.
const RING_EVENT_IDX = 1 << 29;
const UNUSED = 1 << 30; // legacy
const VERSION_1 = 1 << 32; // detect legacy
/// device independent: device independent feature: unused feature bit.
const UNUSED = 1 << 30;


// since virtio v1.1
/// Detects legacy features for virtio version 1.0.
const VERSION_1 = 1 << 32;
/// Since virtio v1.1: allows the device to access the platform.
const ACCESS_PLATFORM = 1 << 33;
/// Since virtio v1.1: supports packed virtio rings.
const RING_PACKED = 1 << 34;
/// Since virtio v1.1: ensures descriptors are processed in order.
const IN_ORDER = 1 << 35;
/// Since virtio v1.1: allows the device to order operations on the platform.
const ORDER_PLATFORM = 1 << 36;
/// Since virtio v1.1: supports single root I/O virtualization.
const SR_IOV = 1 << 37;
/// Since virtio v1.1: supports notification data feature.
const NOTIFICATION_DATA = 1 << 38;
}
}
4 changes: 3 additions & 1 deletion src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ pub mod net;

pub mod rng;

pub mod utility;

pub mod socket;
#[cfg(feature = "alloc")]
pub mod sound;

pub(crate) mod common;
pub mod common;
57 changes: 57 additions & 0 deletions src/device/utility.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! Driver for generic VirtIO devices.
use super::common::Feature;
use crate::{queue::VirtQueue, transport::Transport, Hal, Result};

// VirtioUtility only uses one queue
const QUEUE_IDX: u16 = 0;
const SUPPORTED_FEATURES: Feature = Feature::RING_INDIRECT_DESC.union(Feature::RING_EVENT_IDX);

/// Driver for generic VirtIO device.
pub struct VirtIOUtility<H: Hal, T: Transport, const SIZE: usize> {
transport: T,
queue: VirtQueue<H, SIZE>,
}

impl<H: Hal, T: Transport, const SIZE: usize> VirtIOUtility<H, T, SIZE> {
/// Create a new driver with the given transport.
pub fn new(mut transport: T, features: Feature) -> Result<Self> {
let feat = transport.begin_init(features);
let queue = VirtQueue::new(
&mut transport,
QUEUE_IDX,
feat.contains(Feature::RING_INDIRECT_DESC),
feat.contains(Feature::RING_EVENT_IDX),
)?;
transport.finish_init();
Ok(Self { transport, queue })
}

/// Request from the device to be read from `dst`,and to be written into `src`.
pub fn request(&mut self, src: &[u8], dst: &mut [u8]) -> Result<usize> {
let num = self
.queue
.add_notify_wait_pop(&[src], &mut [dst], &mut self.transport)?;
Ok(num as usize)
}

/// Enable interrupts.
pub fn enable_interrupts(&mut self) {
self.queue.set_dev_notify(true);
}

/// Disable interrupts.
pub fn disable_interrupts(&mut self) {
self.queue.set_dev_notify(false);
}

/// Acknowledge interrupt.
pub fn ack_interrupt(&mut self) -> bool {
self.transport.ack_interrupt()
}
}

impl<H: Hal, T: Transport, const SIZE: usize> Drop for VirtIOUtility<H, T, SIZE> {
fn drop(&mut self) {
self.transport.queue_unset(QUEUE_IDX);
}
}
Loading