diff options
Diffstat (limited to 'rust/hw/char/pl011/src/memory_ops.rs')
| -rw-r--r-- | rust/hw/char/pl011/src/memory_ops.rs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/rust/hw/char/pl011/src/memory_ops.rs b/rust/hw/char/pl011/src/memory_ops.rs new file mode 100644 index 0000000000..8d066ebf6d --- /dev/null +++ b/rust/hw/char/pl011/src/memory_ops.rs @@ -0,0 +1,59 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +use core::{mem::MaybeUninit, ptr::NonNull}; + +use qemu_api::bindings::*; + +use crate::device::PL011State; + +pub static PL011_OPS: MemoryRegionOps = MemoryRegionOps { + read: Some(pl011_read), + write: Some(pl011_write), + read_with_attrs: None, + write_with_attrs: None, + endianness: device_endian::DEVICE_NATIVE_ENDIAN, + valid: unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_1>::zeroed().assume_init() }, + impl_: MemoryRegionOps__bindgen_ty_2 { + min_access_size: 4, + max_access_size: 4, + ..unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_2>::zeroed().assume_init() } + }, +}; + +#[no_mangle] +unsafe extern "C" fn pl011_read( + opaque: *mut core::ffi::c_void, + addr: hwaddr, + size: core::ffi::c_uint, +) -> u64 { + assert!(!opaque.is_null()); + let mut state = unsafe { NonNull::new_unchecked(opaque.cast::<PL011State>()) }; + let val = unsafe { state.as_mut().read(addr, size) }; + match val { + std::ops::ControlFlow::Break(val) => val, + std::ops::ControlFlow::Continue(val) => { + // SAFETY: self.char_backend is a valid CharBackend instance after it's been + // initialized in realize(). + let cb_ptr = unsafe { core::ptr::addr_of_mut!(state.as_mut().char_backend) }; + unsafe { qemu_chr_fe_accept_input(cb_ptr) }; + + val + } + } +} + +#[no_mangle] +unsafe extern "C" fn pl011_write( + opaque: *mut core::ffi::c_void, + addr: hwaddr, + data: u64, + _size: core::ffi::c_uint, +) { + unsafe { + assert!(!opaque.is_null()); + let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>()); + state.as_mut().write(addr, data) + } +} |