// Copyright 2024, Linaro Limited // Author(s): Manos Pitsidianakis // 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::::zeroed().assume_init() }, impl_: MemoryRegionOps__bindgen_ty_2 { min_access_size: 4, max_access_size: 4, ..unsafe { MaybeUninit::::zeroed().assume_init() } }, }; 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::()) }; 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 } } } 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::()); state.as_mut().write(addr, data) } }