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::ptr::NonNull; 6 use std::os::raw::{c_uint, c_void}; 7 8 use qemu_api::{bindings::*, zeroable::Zeroable}; 9 10 use crate::device::PL011State; 11 12 pub static PL011_OPS: MemoryRegionOps = MemoryRegionOps { 13 read: Some(pl011_read), 14 write: Some(pl011_write), 15 read_with_attrs: None, 16 write_with_attrs: None, 17 endianness: device_endian::DEVICE_NATIVE_ENDIAN, 18 valid: Zeroable::ZERO, 19 impl_: MemoryRegionOps__bindgen_ty_2 { 20 min_access_size: 4, 21 max_access_size: 4, 22 ..Zeroable::ZERO 23 }, 24 }; 25 26 unsafe extern "C" fn pl011_read(opaque: *mut c_void, addr: hwaddr, size: c_uint) -> u64 { 27 assert!(!opaque.is_null()); 28 let mut state = unsafe { NonNull::new_unchecked(opaque.cast::<PL011State>()) }; 29 let val = unsafe { state.as_mut().read(addr, size) }; 30 match val { 31 std::ops::ControlFlow::Break(val) => val, 32 std::ops::ControlFlow::Continue(val) => { 33 // SAFETY: self.char_backend is a valid CharBackend instance after it's been 34 // initialized in realize(). 35 let cb_ptr = unsafe { core::ptr::addr_of_mut!(state.as_mut().char_backend) }; 36 unsafe { qemu_chr_fe_accept_input(cb_ptr) }; 37 38 val 39 } 40 } 41 } 42 43 unsafe extern "C" fn pl011_write(opaque: *mut c_void, addr: hwaddr, data: u64, _size: c_uint) { 44 unsafe { 45 assert!(!opaque.is_null()); 46 let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>()); 47 state.as_mut().write(addr, data) 48 } 49 } 50