Skip to content

Commit 0b36adc

Browse files
committed
feature: add generic device named as utility
1 parent 9de4d8e commit 0b36adc

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

src/device/common.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,36 @@ use bitflags::bitflags;
44

55
bitflags! {
66
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
7-
pub(crate) struct Feature: u64 {
8-
// device independent
9-
const NOTIFY_ON_EMPTY = 1 << 24; // legacy
10-
const ANY_LAYOUT = 1 << 27; // legacy
7+
/// The features supported by the virtio device.
8+
pub struct Feature: u64 {
9+
/// Mount the shared directory using the mount_tag method.
10+
const VIRTIO_9P_F_MOUNT_TAG = 1 << 0;
11+
12+
/// device independent: notifies when the queue is empty.
13+
const NOTIFY_ON_EMPTY = 1 << 24;
14+
/// device independent: allows any layout for the queue.
15+
const ANY_LAYOUT = 1 << 27;
16+
/// device independent: Supports indirect descriptors in the virtio ring.
1117
const RING_INDIRECT_DESC = 1 << 28;
18+
/// device independent: Supports event index feature in the virtio ring.
1219
const RING_EVENT_IDX = 1 << 29;
13-
const UNUSED = 1 << 30; // legacy
14-
const VERSION_1 = 1 << 32; // detect legacy
20+
/// device independent: device independent feature: unused feature bit.
21+
const UNUSED = 1 << 30;
22+
1523

16-
// since virtio v1.1
24+
/// Detects legacy features for virtio version 1.0.
25+
const VERSION_1 = 1 << 32;
26+
/// Since virtio v1.1: allows the device to access the platform.
1727
const ACCESS_PLATFORM = 1 << 33;
28+
/// Since virtio v1.1: supports packed virtio rings.
1829
const RING_PACKED = 1 << 34;
30+
/// Since virtio v1.1: ensures descriptors are processed in order.
1931
const IN_ORDER = 1 << 35;
32+
/// Since virtio v1.1: allows the device to order operations on the platform.
2033
const ORDER_PLATFORM = 1 << 36;
34+
/// Since virtio v1.1: supports single root I/O virtualization.
2135
const SR_IOV = 1 << 37;
36+
/// Since virtio v1.1: supports notification data feature.
2237
const NOTIFICATION_DATA = 1 << 38;
2338
}
2439
}

src/device/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ pub mod net;
1212

1313
pub mod rng;
1414

15+
pub mod utility;
16+
1517
pub mod socket;
1618
#[cfg(feature = "alloc")]
1719
pub mod sound;
1820

19-
pub(crate) mod common;
21+
pub mod common;

src/device/utility.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! Driver for generic VirtIO devices.
2+
use super::common::Feature;
3+
use crate::{queue::VirtQueue, transport::Transport, Hal, Result};
4+
5+
// VirtioUtility only uses one queue
6+
const QUEUE_IDX: u16 = 0;
7+
const SUPPORTED_FEATURES: Feature = Feature::RING_INDIRECT_DESC.union(Feature::RING_EVENT_IDX);
8+
9+
/// Driver for generic VirtIO device.
10+
pub struct VirtIOUtility<H: Hal, T: Transport, const SIZE: usize> {
11+
transport: T,
12+
queue: VirtQueue<H, SIZE>,
13+
}
14+
15+
impl<H: Hal, T: Transport, const SIZE: usize> VirtIOUtility<H, T, SIZE> {
16+
/// Create a new driver with the given transport.
17+
pub fn new(mut transport: T, features: Feature) -> Result<Self> {
18+
let feat = transport.begin_init(features);
19+
let queue = VirtQueue::new(
20+
&mut transport,
21+
QUEUE_IDX,
22+
feat.contains(Feature::RING_INDIRECT_DESC),
23+
feat.contains(Feature::RING_EVENT_IDX),
24+
)?;
25+
transport.finish_init();
26+
Ok(Self { transport, queue })
27+
}
28+
29+
/// Request from the device to be read from `dst`,and to be written into `src`.
30+
pub fn request(&mut self, src: &[u8], dst: &mut [u8]) -> Result<usize> {
31+
let num = self
32+
.queue
33+
.add_notify_wait_pop(&[src], &mut [dst], &mut self.transport)?;
34+
Ok(num as usize)
35+
}
36+
37+
/// Enable interrupts.
38+
pub fn enable_interrupts(&mut self) {
39+
self.queue.set_dev_notify(true);
40+
}
41+
42+
/// Disable interrupts.
43+
pub fn disable_interrupts(&mut self) {
44+
self.queue.set_dev_notify(false);
45+
}
46+
47+
/// Acknowledge interrupt.
48+
pub fn ack_interrupt(&mut self) -> bool {
49+
self.transport.ack_interrupt()
50+
}
51+
}
52+
53+
impl<H: Hal, T: Transport, const SIZE: usize> Drop for VirtIOUtility<H, T, SIZE> {
54+
fn drop(&mut self) {
55+
self.transport.queue_unset(QUEUE_IDX);
56+
}
57+
}

0 commit comments

Comments
 (0)