|
| 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