sel4_microkit_base/
channel.rs
1use core::fmt;
8
9use crate::{
10 symbols::{pd_irqs, pd_notifications, pd_pps},
11 MessageInfo,
12};
13
14const BASE_OUTPUT_NOTIFICATION_SLOT: usize = 10;
15const BASE_ENDPOINT_SLOT: usize = BASE_OUTPUT_NOTIFICATION_SLOT + 64;
16const BASE_IRQ_SLOT: usize = BASE_ENDPOINT_SLOT + 64;
17const BASE_TCB_SLOT: usize = BASE_IRQ_SLOT + 64;
18
19const MAX_CHANNELS: usize = 62;
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
23pub struct Channel {
24 index: usize,
25}
26
27impl Channel {
28 pub const fn new(index: usize) -> Self {
29 assert!(index < MAX_CHANNELS);
30 Self { index }
31 }
32
33 pub const fn index(&self) -> usize {
34 self.index
35 }
36
37 fn cap<T: ChannelFacet>(&self) -> sel4::Cap<T> {
38 if T::mask() & (1 << self.index) == 0 {
39 panic!("{}: not valid for channel '{}'", T::METHOD_NAME, self.index);
40 }
41 sel4::Cap::from_bits((T::BASE_SLOT + self.index) as sel4::CPtrBits)
42 }
43
44 #[doc(hidden)]
45 pub fn notification(&self) -> sel4::cap::Notification {
46 self.cap::<sel4::cap_type::Notification>()
47 }
48
49 #[doc(hidden)]
50 pub fn irq_handler(&self) -> sel4::cap::IrqHandler {
51 self.cap::<sel4::cap_type::IrqHandler>()
52 }
53
54 #[doc(hidden)]
55 pub fn endpoint(&self) -> sel4::cap::Endpoint {
56 self.cap::<sel4::cap_type::Endpoint>()
57 }
58
59 pub fn notify(&self) {
60 self.notification().signal()
61 }
62
63 pub fn irq_ack(&self) -> Result<(), IrqAckError> {
64 self.irq_handler()
65 .irq_handler_ack()
66 .map_err(IrqAckError::from_inner)
67 }
68
69 pub fn pp_call(&self, msg_info: MessageInfo) -> MessageInfo {
70 MessageInfo::from_inner(self.endpoint().call(msg_info.into_inner()))
71 }
72}
73
74trait ChannelFacet: sel4::CapType {
75 const METHOD_NAME: &str;
76 const BASE_SLOT: usize;
77
78 fn mask() -> usize;
79}
80
81impl ChannelFacet for sel4::cap_type::Notification {
82 const METHOD_NAME: &str = "pp_call";
83 const BASE_SLOT: usize = BASE_OUTPUT_NOTIFICATION_SLOT;
84
85 fn mask() -> usize {
86 pd_notifications()
87 }
88}
89
90impl ChannelFacet for sel4::cap_type::IrqHandler {
91 const METHOD_NAME: &str = "irq_ack";
92 const BASE_SLOT: usize = BASE_IRQ_SLOT;
93
94 fn mask() -> usize {
95 pd_irqs()
96 }
97}
98
99impl ChannelFacet for sel4::cap_type::Endpoint {
100 const METHOD_NAME: &str = "notify";
101 const BASE_SLOT: usize = BASE_ENDPOINT_SLOT;
102
103 fn mask() -> usize {
104 pd_pps()
105 }
106}
107
108#[derive(Debug, PartialEq, Eq)]
110pub struct IrqAckError(sel4::Error);
111
112impl IrqAckError {
113 fn from_inner(inner: sel4::Error) -> Self {
114 Self(inner)
115 }
116
117 fn inner(&self) -> &sel4::Error {
118 &self.0
119 }
120}
121
122impl fmt::Display for IrqAckError {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 write!(f, "irq ack error: {:?}", self.inner())
125 }
126}
127
128#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
130pub struct Child {
131 index: usize,
132}
133
134impl Child {
135 pub const fn new(index: usize) -> Self {
136 Self { index }
137 }
138
139 pub const fn index(&self) -> usize {
140 self.index
141 }
142
143 #[doc(hidden)]
144 pub fn tcb(&self) -> sel4::cap::Tcb {
145 sel4::Cap::from_bits((BASE_TCB_SLOT + self.index) as sel4::CPtrBits)
146 }
147}