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