Pārlūkot izejas kodu

Use heap rather than DMA buffer for console RX buffer.

The buffer is shared with the device via the HAL when it's added to the
queue, so it doesn't need to be a DMA buffer itself.
Andrew Walbran 1 gadu atpakaļ
vecāks
revīzija
d5f0ae0f90
3 mainītis faili ar 20 papildinājumiem un 13 dzēšanām
  1. 17 13
      src/device/console.rs
  2. 1 0
      src/device/mod.rs
  3. 2 0
      src/lib.rs

+ 17 - 13
src/device/console.rs

@@ -1,10 +1,11 @@
 //! Driver for VirtIO console devices.
 
-use crate::hal::{BufferDirection, Dma, Hal};
+use crate::hal::Hal;
 use crate::queue::VirtQueue;
 use crate::transport::Transport;
 use crate::volatile::{volread, ReadOnly, WriteOnly};
-use crate::Result;
+use crate::{Result, PAGE_SIZE};
+use alloc::boxed::Box;
 use bitflags::bitflags;
 use core::ptr::NonNull;
 use log::info;
@@ -38,13 +39,12 @@ const QUEUE_SIZE: usize = 2;
 /// # Ok(())
 /// # }
 /// ```
-pub struct VirtIOConsole<'a, H: Hal, T: Transport> {
+pub struct VirtIOConsole<H: Hal, T: Transport> {
     transport: T,
     config_space: NonNull<Config>,
     receiveq: VirtQueue<H, QUEUE_SIZE>,
     transmitq: VirtQueue<H, QUEUE_SIZE>,
-    queue_buf_dma: Dma<H>,
-    queue_buf_rx: &'a mut [u8],
+    queue_buf_rx: Box<[u8; PAGE_SIZE]>,
     cursor: usize,
     pending_len: usize,
     /// The token of the outstanding receive request, if there is one.
@@ -62,7 +62,7 @@ pub struct ConsoleInfo {
     pub max_ports: u32,
 }
 
-impl<H: Hal, T: Transport> VirtIOConsole<'_, H, T> {
+impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
     /// Creates a new VirtIO console driver.
     pub fn new(mut transport: T) -> Result<Self> {
         transport.begin_init(|features| {
@@ -74,12 +74,11 @@ impl<H: Hal, T: Transport> VirtIOConsole<'_, H, T> {
         let config_space = transport.config_space::<Config>()?;
         let receiveq = VirtQueue::new(&mut transport, QUEUE_RECEIVEQ_PORT_0)?;
         let transmitq = VirtQueue::new(&mut transport, QUEUE_TRANSMITQ_PORT_0)?;
-        let queue_buf_dma = Dma::new(1, BufferDirection::DeviceToDriver)?;
 
         // Safe because no alignment or initialisation is required for [u8], the DMA buffer is
         // dereferenceable, and the lifetime of the reference matches the lifetime of the DMA buffer
         // (which we don't otherwise access).
-        let queue_buf_rx = unsafe { queue_buf_dma.raw_slice().as_mut() };
+        let queue_buf_rx = Box::new([0; PAGE_SIZE]);
 
         transport.finish_init();
         let mut console = VirtIOConsole {
@@ -87,7 +86,6 @@ impl<H: Hal, T: Transport> VirtIOConsole<'_, H, T> {
             config_space,
             receiveq,
             transmitq,
-            queue_buf_dma,
             queue_buf_rx,
             cursor: 0,
             pending_len: 0,
@@ -118,7 +116,10 @@ impl<H: Hal, T: Transport> VirtIOConsole<'_, H, T> {
         if self.receive_token.is_none() && self.cursor == self.pending_len {
             // Safe because the buffer lasts at least as long as the queue, and there are no other
             // outstanding requests using the buffer.
-            self.receive_token = Some(unsafe { self.receiveq.add(&[], &mut [self.queue_buf_rx]) }?);
+            self.receive_token = Some(unsafe {
+                self.receiveq
+                    .add(&[], &mut [self.queue_buf_rx.as_mut_slice()])
+            }?);
             if self.receiveq.should_notify() {
                 self.transport.notify(QUEUE_RECEIVEQ_PORT_0);
             }
@@ -148,8 +149,11 @@ impl<H: Hal, T: Transport> VirtIOConsole<'_, H, T> {
                 // Safe because we are passing the same buffer as we passed to `VirtQueue::add` in
                 // `poll_retrieve` and it is still valid.
                 let len = unsafe {
-                    self.receiveq
-                        .pop_used(receive_token, &[], &mut [self.queue_buf_rx])?
+                    self.receiveq.pop_used(
+                        receive_token,
+                        &[],
+                        &mut [self.queue_buf_rx.as_mut_slice()],
+                    )?
                 };
                 flag = true;
                 assert_ne!(len, 0);
@@ -188,7 +192,7 @@ impl<H: Hal, T: Transport> VirtIOConsole<'_, H, T> {
     }
 }
 
-impl<H: Hal, T: Transport> Drop for VirtIOConsole<'_, H, T> {
+impl<H: Hal, T: Transport> Drop for VirtIOConsole<H, T> {
     fn drop(&mut self) {
         // Clear any pointers pointing to DMA regions, so the device doesn't try to access them
         // after they have been freed.

+ 1 - 0
src/device/mod.rs

@@ -1,6 +1,7 @@
 //! Drivers for specific VirtIO devices.
 
 pub mod blk;
+#[cfg(feature = "alloc")]
 pub mod console;
 pub mod gpu;
 #[cfg(feature = "alloc")]

+ 2 - 0
src/lib.rs

@@ -24,12 +24,14 @@
 //!
 //! ```
 //! # use virtio_drivers::Hal;
+//! # #[cfg(feature = "alloc")]
 //! use virtio_drivers::{
 //!     device::console::VirtIOConsole,
 //!     transport::{mmio::MmioTransport, DeviceType, Transport},
 //! };
 
 //!
+//! # #[cfg(feature = "alloc")]
 //! # fn example<HalImpl: Hal>(transport: MmioTransport) {
 //! if transport.device_type() == DeviceType::Console {
 //!     let mut console = VirtIOConsole::<HalImpl, _>::new(transport).unwrap();