// Copyright 2024, Linaro Limited // Author(s): Manos Pitsidianakis // SPDX-License-Identifier: GPL-2.0-or-later use core::ptr::NonNull; use std::os::raw::{c_uint, c_void}; use qemu_api::{bindings::*, zeroable::Zeroable}; 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: Zeroable::ZERO, impl_: MemoryRegionOps__bindgen_ty_2 { min_access_size: 4, max_access_size: 4, ..Zeroable::ZERO }, }; unsafe extern "C" fn pl011_read(opaque: *mut c_void, addr: hwaddr, size: 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 c_void, addr: hwaddr, data: u64, _size: c_uint) { unsafe { assert!(!opaque.is_null()); let mut state = NonNull::new_unchecked(opaque.cast::()); state.as_mut().write(addr, data) } }