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 unsafe extern "C" fn pl011_read( 26 opaque: *mut core::ffi::c_void, 27 addr: hwaddr, 28 size: core::ffi::c_uint, 29 ) -> u64 { 30 assert!(!opaque.is_null()); 31 let mut state = unsafe { NonNull::new_unchecked(opaque.cast::<PL011State>()) }; 32 let val = unsafe { state.as_mut().read(addr, size) }; 33 match val { 34 std::ops::ControlFlow::Break(val) => val, 35 std::ops::ControlFlow::Continue(val) => { 36 // SAFETY: self.char_backend is a valid CharBackend instance after it's been 37 // initialized in realize(). 38 let cb_ptr = unsafe { core::ptr::addr_of_mut!(state.as_mut().char_backend) }; 39 unsafe { qemu_chr_fe_accept_input(cb_ptr) }; 40 41 val 42 } 43 } 44 } 45 46 unsafe extern "C" fn pl011_write( 47 opaque: *mut core::ffi::c_void, 48 addr: hwaddr, 49 data: u64, 50 _size: core::ffi::c_uint, 51 ) { 52 unsafe { 53 assert!(!opaque.is_null()); 54 let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>()); 55 state.as_mut().write(addr, data) 56 } 57 } 58