use alloc::sync::Arc;
use super::{
InterruptControllerId, InterruptEndpoint, IrqResult, ItsId, LpiId, MsiDeviceId, MsiEventId,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct MsiMessage {
its: ItsId,
device: MsiDeviceId,
event: MsiEventId,
lpi: LpiId,
}
impl MsiMessage {
pub const fn new(its: ItsId, device: MsiDeviceId, event: MsiEventId, lpi: LpiId) -> Self {
Self {
its,
device,
event,
lpi,
}
}
pub const fn its(self) -> ItsId {
self.its
}
pub const fn device(self) -> MsiDeviceId {
self.device
}
pub const fn event(self) -> MsiEventId {
self.event
}
pub const fn lpi(self) -> LpiId {
self.lpi
}
}
pub trait MessageInterruptController: Send + Sync {
fn id(&self) -> InterruptControllerId;
fn msi_endpoint(
&self,
its: ItsId,
device: MsiDeviceId,
event: MsiEventId,
lpi: LpiId,
) -> IrqResult<MsiEndpoint>;
}
pub trait MessageInterruptSink: Send + Sync {
fn signal(&self, message: MsiMessage) -> IrqResult;
}
#[derive(Clone)]
pub struct MsiEndpoint {
controller: InterruptControllerId,
message: MsiMessage,
sink: Arc<dyn MessageInterruptSink>,
}
impl MsiEndpoint {
pub fn new(
controller: InterruptControllerId,
message: MsiMessage,
sink: Arc<dyn MessageInterruptSink>,
) -> Self {
Self {
controller,
message,
sink,
}
}
pub fn signal(&self) -> IrqResult {
self.sink.signal(self.message)
}
pub const fn controller(&self) -> InterruptControllerId {
self.controller
}
pub const fn message(&self) -> MsiMessage {
self.message
}
pub const fn diagnostic_endpoint(&self) -> InterruptEndpoint {
InterruptEndpoint::Message {
controller: self.controller,
its: self.message.its,
device: self.message.device,
event: self.message.event,
lpi: self.message.lpi,
}
}
}
impl core::fmt::Debug for MsiEndpoint {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter
.debug_struct("MsiEndpoint")
.field("controller", &self.controller)
.field("message", &self.message)
.finish_non_exhaustive()
}
}