mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
rust: add bindings for gpio_{in|out} initialization
Wrap qdev_init_gpio_{in|out} as methods in DeviceMethods. And for qdev_init_gpio_in, based on FnCall, it can support idiomatic Rust callback without the need for C style wrapper. Signed-off-by: Zhao Liu <zhao1.liu@intel.com> Link: https://lore.kernel.org/r/20250210030051.2562726-5-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e6f1195f55
commit
9a96d41007
2 changed files with 43 additions and 5 deletions
|
@ -84,7 +84,6 @@ where
|
||||||
self.cell.as_ptr()
|
self.cell.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) const fn slice_as_ptr(slice: &[Self]) -> *mut *mut IRQState {
|
pub(crate) const fn slice_as_ptr(slice: &[Self]) -> *mut *mut IRQState {
|
||||||
assert!(!slice.is_empty());
|
assert!(!slice.is_empty());
|
||||||
slice[0].as_ptr()
|
slice[0].as_ptr()
|
||||||
|
|
|
@ -6,17 +6,18 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
os::raw::c_void,
|
os::raw::{c_int, c_void},
|
||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use bindings::{Clock, ClockEvent, DeviceClass, DeviceState, Property, ResetType};
|
pub use bindings::{Clock, ClockEvent, DeviceClass, DeviceState, Property, ResetType};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bindings::{self, Error, ResettableClass},
|
bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, Error, ResettableClass},
|
||||||
callbacks::FnCall,
|
callbacks::FnCall,
|
||||||
cell::bql_locked,
|
cell::bql_locked,
|
||||||
chardev::Chardev,
|
chardev::Chardev,
|
||||||
|
irq::InterruptSource,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
qom::{ClassInitImpl, ObjectClass, ObjectImpl, Owned},
|
qom::{ClassInitImpl, ObjectClass, ObjectImpl, Owned},
|
||||||
vmstate::VMStateDescription,
|
vmstate::VMStateDescription,
|
||||||
|
@ -28,8 +29,8 @@ pub trait ResettablePhasesImpl {
|
||||||
/// If not None, this is called when the object enters reset. It
|
/// If not None, this is called when the object enters reset. It
|
||||||
/// can reset local state of the object, but it must not do anything that
|
/// can reset local state of the object, but it must not do anything that
|
||||||
/// has a side-effect on other objects, such as raising or lowering an
|
/// has a side-effect on other objects, such as raising or lowering an
|
||||||
/// [`InterruptSource`](crate::irq::InterruptSource), or reading or
|
/// [`InterruptSource`], or reading or writing guest memory. It takes the
|
||||||
/// writing guest memory. It takes the reset's type as argument.
|
/// reset's type as argument.
|
||||||
const ENTER: Option<fn(&Self, ResetType)> = None;
|
const ENTER: Option<fn(&Self, ResetType)> = None;
|
||||||
|
|
||||||
/// If not None, this is called when the object for entry into reset, once
|
/// If not None, this is called when the object for entry into reset, once
|
||||||
|
@ -318,6 +319,44 @@ where
|
||||||
bindings::qdev_prop_set_chr(self.as_mut_ptr(), c_propname.as_ptr(), chr.as_mut_ptr());
|
bindings::qdev_prop_set_chr(self.as_mut_ptr(), c_propname.as_ptr(), chr.as_mut_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_gpio_in<F: for<'a> FnCall<(&'a Self::Target, u32, u32)>>(
|
||||||
|
&self,
|
||||||
|
num_lines: u32,
|
||||||
|
_cb: F,
|
||||||
|
) {
|
||||||
|
let _: () = F::ASSERT_IS_SOME;
|
||||||
|
|
||||||
|
unsafe extern "C" fn rust_irq_handler<T, F: for<'a> FnCall<(&'a T, u32, u32)>>(
|
||||||
|
opaque: *mut c_void,
|
||||||
|
line: c_int,
|
||||||
|
level: c_int,
|
||||||
|
) {
|
||||||
|
// SAFETY: the opaque was passed as a reference to `T`
|
||||||
|
F::call((unsafe { &*(opaque.cast::<T>()) }, line as u32, level as u32))
|
||||||
|
}
|
||||||
|
|
||||||
|
let gpio_in_cb: unsafe extern "C" fn(*mut c_void, c_int, c_int) =
|
||||||
|
rust_irq_handler::<Self::Target, F>;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
qdev_init_gpio_in(
|
||||||
|
self.as_mut_ptr::<DeviceState>(),
|
||||||
|
Some(gpio_in_cb),
|
||||||
|
num_lines as c_int,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_gpio_out(&self, pins: &[InterruptSource]) {
|
||||||
|
unsafe {
|
||||||
|
qdev_init_gpio_out(
|
||||||
|
self.as_mut_ptr::<DeviceState>(),
|
||||||
|
InterruptSource::slice_as_ptr(pins),
|
||||||
|
pins.len() as c_int,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: ObjectDeref> DeviceMethods for R where R::Target: IsA<DeviceState> {}
|
impl<R: ObjectDeref> DeviceMethods for R where R::Target: IsA<DeviceState> {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue