1 // Copyright 2024, Linaro Limited 2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 use core::{mem::MaybeUninit, ptr::NonNull}; 6 7 use qemu_api::bindings::*; 8 9 use crate::device::PL011State; 10 11 pub static PL011_OPS: MemoryRegionOps = MemoryRegionOps { 12 read: Some(pl011_read), 13 write: Some(pl011_write), 14 read_with_attrs: None, 15 write_with_attrs: None, 16 endianness: device_endian::DEVICE_NATIVE_ENDIAN, 17 valid: unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_1>::zeroed().assume_init() }, 18 impl_: MemoryRegionOps__bindgen_ty_2 { 19 min_access_size: 4, 20 max_access_size: 4, 21 ..unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_2>::zeroed().assume_init() } 22 }, 23 }; 24 25 #[no_mangle] 26 unsafe extern "C" fn pl011_read( 27 opaque: *mut core::ffi::c_void, 28 addr: hwaddr, 29 size: core::ffi::c_uint, 30 ) -> u64 { 31 assert!(!opaque.is_null()); 32 let mut state = unsafe { NonNull::new_unchecked(opaque.cast::<PL011State>()) }; 33 let val = unsafe { state.as_mut().read(addr, size) }; 34 match val { 35 std::ops::ControlFlow::Break(val) => val, 36 std::ops::ControlFlow::Continue(val) => { 37 // SAFETY: self.char_backend is a valid CharBackend instance after it's been 38 // initialized in realize(). 39 let cb_ptr = unsafe { core::ptr::addr_of_mut!(state.as_mut().char_backend) }; 40 unsafe { qemu_chr_fe_accept_input(cb_ptr) }; 41 42 val 43 } 44 } 45 } 46 47 #[no_mangle] 48 unsafe extern "C" fn pl011_write( 49 opaque: *mut core::ffi::c_void, 50 addr: hwaddr, 51 data: u64, 52 _size: core::ffi::c_uint, 53 ) { 54 unsafe { 55 assert!(!opaque.is_null()); 56 let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>()); 57 state.as_mut().write(addr, data) 58 } 59 } 60