virtio_drivers/device/
rng.rs1use super::common::Feature;
3use crate::{
4 queue::VirtQueue,
5 transport::{InterruptStatus, Transport},
6 Hal, Result,
7};
8
9const QUEUE_IDX: u16 = 0;
11const QUEUE_SIZE: usize = 8;
12const SUPPORTED_FEATURES: Feature = Feature::RING_INDIRECT_DESC
13 .union(Feature::RING_EVENT_IDX)
14 .union(Feature::VERSION_1);
15
16pub struct VirtIORng<H: Hal, T: Transport> {
18 transport: T,
19 queue: VirtQueue<H, QUEUE_SIZE>,
20}
21
22impl<H: Hal, T: Transport> VirtIORng<H, T> {
23 pub fn new(mut transport: T) -> Result<Self> {
25 let feat = transport.begin_init(SUPPORTED_FEATURES);
26 let queue = VirtQueue::new(
27 &mut transport,
28 QUEUE_IDX,
29 feat.contains(Feature::RING_INDIRECT_DESC),
30 feat.contains(Feature::RING_EVENT_IDX),
31 )?;
32 transport.finish_init();
33 Ok(Self { transport, queue })
34 }
35
36 pub fn request_entropy(&mut self, dst: &mut [u8]) -> Result<usize> {
38 let num = self
39 .queue
40 .add_notify_wait_pop(&[], &mut [dst], &mut self.transport)?;
41 Ok(num as usize)
42 }
43
44 pub fn enable_interrupts(&mut self) {
46 self.queue.set_dev_notify(true);
47 }
48
49 pub fn disable_interrupts(&mut self) {
51 self.queue.set_dev_notify(false);
52 }
53
54 pub fn ack_interrupt(&mut self) -> InterruptStatus {
56 self.transport.ack_interrupt()
57 }
58}
59
60impl<H: Hal, T: Transport> Drop for VirtIORng<H, T> {
61 fn drop(&mut self) {
62 self.transport.queue_unset(QUEUE_IDX);
63 }
64}