Skip to content

Commit

Permalink
Add support for emergency writes.
Browse files Browse the repository at this point in the history
  • Loading branch information
qwandor committed Aug 6, 2024
1 parent 5d92979 commit 64a8a3c
Showing 1 changed file with 44 additions and 3 deletions.
47 changes: 44 additions & 3 deletions src/device/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use crate::hal::Hal;
use crate::queue::VirtQueue;
use crate::transport::Transport;
use crate::volatile::{volread, ReadOnly, WriteOnly};
use crate::{Result, PAGE_SIZE};
use crate::volatile::{volread, volwrite, ReadOnly, WriteOnly};
use crate::{Error, Result, PAGE_SIZE};
use alloc::boxed::Box;
use bitflags::bitflags;
use core::{
Expand All @@ -17,7 +17,8 @@ const QUEUE_TRANSMITQ_PORT_0: u16 = 1;
const QUEUE_SIZE: usize = 2;
const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX
.union(Features::RING_INDIRECT_DESC)
.union(Features::SIZE);
.union(Features::SIZE)
.union(Features::EMERG_WRITE);

/// Driver for a VirtIO console device.
///
Expand Down Expand Up @@ -217,6 +218,21 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
.add_notify_wait_pop(&[&buf], &mut [], &mut self.transport)?;
Ok(())
}

/// Sends a character to the console using the emergency write feature.
///
/// Returns an error if the device doesn't support emergency write.
pub fn emergency_write(&mut self, chr: u8) -> Result<()> {
if self.negotiated_features.contains(Features::EMERG_WRITE) {
// SAFETY: `self.config_space` is a valid pointer to the device configuration space.
unsafe {
volwrite!(self.config_space, emerg_wr, chr.into());
}
Ok(())
} else {
Err(Error::Unsupported)
}
}
}

impl<H: Hal, T: Transport> Drop for VirtIOConsole<H, T> {
Expand Down Expand Up @@ -329,6 +345,31 @@ mod tests {
);
}

#[test]
fn emergency_write() {
let mut config_space = Config {
cols: ReadOnly::new(0),
rows: ReadOnly::new(0),
max_nr_ports: ReadOnly::new(0),
emerg_wr: WriteOnly::default(),
};
let state = Arc::new(Mutex::new(State {
queues: vec![QueueStatus::default(), QueueStatus::default()],
..Default::default()
}));
let transport = FakeTransport {
device_type: DeviceType::Console,
max_queue_size: 2,
device_features: 0x07,
config_space: NonNull::from(&mut config_space),
state: state.clone(),
};
let mut console = VirtIOConsole::<FakeHal, FakeTransport<Config>>::new(transport).unwrap();

console.emergency_write(42).unwrap();
assert_eq!(config_space.emerg_wr.0, 42);
}

#[test]
fn receive() {
let mut config_space = Config {
Expand Down

0 comments on commit 64a8a3c

Please sign in to comment.