1use chipset_device::io::IoResult;
7use chipset_device::io::deferred::DeferredRead;
8use chipset_device::io::deferred::DeferredToken;
9use chipset_device::io::deferred::DeferredWrite;
10use chipset_device::io::deferred::defer_read;
11use chipset_device::io::deferred::defer_write;
12use chipset_device::pci::ByteEnabledDwordRead;
13use chipset_device::pci::ByteEnabledDwordWrite;
14use chipset_device::pci::PciConfigAddress;
15use chipset_device::pci::PciConfigByteEnable;
16use inspect::Inspect;
17use std::task::Context;
18use std::task::Poll;
19use zerocopy::IntoBytes;
20
21pub trait PciBusCfgAccessCallbacks {
23 fn read(&mut self, addr: PciConfigAddress, value: ByteEnabledDwordRead<'_>) -> IoResult;
25
26 fn write(&mut self, addr: PciConfigAddress, value: ByteEnabledDwordWrite) -> IoResult;
28}
29
30#[derive(Inspect)]
32#[inspect(tag = "kind")]
33enum DeferredCfgAccess {
34 Read {
36 #[inspect(skip)]
37 deferred_device_read: DeferredToken,
38 #[inspect(skip)]
39 bus_read: DeferredRead,
40 addr: PciConfigAddress,
41 byte_enable: PciConfigByteEnable,
42 },
43 Write {
45 #[inspect(skip)]
46 deferred_device_write: DeferredToken,
47 #[inspect(skip)]
48 bus_write: DeferredWrite,
49 addr: PciConfigAddress,
50 },
51}
52
53#[derive(Default, Inspect)]
55pub struct PciBusCfgAccessHandler {
56 #[inspect(with = "|x| x.is_some()")]
57 waker: Option<std::task::Waker>,
58 #[inspect(iter_by_index)]
59 actions: Vec<DeferredCfgAccess>,
60}
61
62impl PciBusCfgAccessHandler {
63 pub fn new() -> Self {
65 Self {
66 waker: None,
67 actions: Vec::new(),
68 }
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self.actions.is_empty()
74 }
75
76 pub fn read(
78 &mut self,
79 addr: PciConfigAddress,
80 mut inline_completion_value: ByteEnabledDwordRead<'_>,
81 callbacks: &mut impl PciBusCfgAccessCallbacks,
82 ) -> IoResult {
83 match callbacks.read(addr, inline_completion_value.reborrow()) {
84 IoResult::Ok => IoResult::Ok,
85 IoResult::Err(err) => IoResult::Err(err),
86 IoResult::Defer(deferred_device_read) => {
87 let (bus_read, bus_token) = defer_read();
88 self.push_action(DeferredCfgAccess::Read {
89 deferred_device_read,
90 bus_read,
91 addr,
92 byte_enable: inline_completion_value.byte_enable(),
93 });
94 IoResult::Defer(bus_token)
95 }
96 }
97 }
98
99 pub fn write(
101 &mut self,
102 addr: PciConfigAddress,
103 value: ByteEnabledDwordWrite,
104 callbacks: &mut impl PciBusCfgAccessCallbacks,
105 ) -> IoResult {
106 let result = callbacks.write(addr, value);
107 if let IoResult::Defer(deferred_device_write) = result {
108 let (bus_write, bus_token) = defer_write();
109 self.push_action(DeferredCfgAccess::Write {
110 deferred_device_write,
111 bus_write,
112 addr,
113 });
114 return IoResult::Defer(bus_token);
115 }
116
117 result
118 }
119
120 pub fn poll(&mut self, cx: &mut Context<'_>) {
122 self.waker = Some(cx.waker().clone());
123 self.actions = std::mem::take(&mut self.actions)
124 .into_iter()
125 .filter_map(|action| match action {
126 DeferredCfgAccess::Read {
127 mut deferred_device_read,
128 bus_read,
129 addr,
130 byte_enable,
131 } => {
132 let mut dword_buffer = 0;
134 if let Poll::Ready(res) =
135 deferred_device_read.poll_read(cx, dword_buffer.as_mut_bytes())
136 {
137 match res {
138 Ok(()) => {
139 let (byte_offset, len) = byte_enable.to_byte_offset_len();
140 let byte_offset = byte_offset as usize;
141 bus_read.complete(
142 &dword_buffer.as_bytes()[byte_offset..byte_offset + len],
143 );
144 }
145 Err(err) => bus_read.complete_error(err),
146 }
147 None
148 } else {
149 Some(DeferredCfgAccess::Read {
152 deferred_device_read,
153 bus_read,
154 addr,
155 byte_enable,
156 })
157 }
158 }
159 DeferredCfgAccess::Write {
160 mut deferred_device_write,
161 bus_write,
162 addr,
163 } => {
164 if let Poll::Ready(res) = deferred_device_write.poll_write(cx) {
166 match res {
167 Ok(()) => bus_write.complete(),
168 Err(err) => bus_write.complete_error(err),
169 }
170 None
171 } else {
172 Some(DeferredCfgAccess::Write {
175 deferred_device_write,
176 bus_write,
177 addr,
178 })
179 }
180 }
181 })
182 .collect();
183 }
184
185 fn push_action(&mut self, action: DeferredCfgAccess) {
186 self.actions.push(action);
187 if let Some(waker) = self.waker.take() {
188 waker.wake();
189 }
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196 use chipset_device::io::IoError;
197
198 #[derive(Clone, Copy)]
199 enum ReadAction {
200 Ok(u32),
201 Err(IoError),
202 Defer,
203 }
204
205 #[derive(Clone, Copy)]
206 enum WriteAction {
207 Ok,
208 Err(IoError),
209 Defer,
210 }
211
212 struct DeferredCallbacks {
213 read_action: ReadAction,
214 write_action: WriteAction,
215 pending_read: Option<DeferredRead>,
216 pending_write: Option<DeferredWrite>,
217 reads: Vec<PciConfigAddress>,
218 writes: Vec<(PciConfigAddress, u32)>,
219 }
220
221 impl DeferredCallbacks {
222 fn new(read_action: ReadAction, write_action: WriteAction) -> Self {
223 Self {
224 read_action,
225 write_action,
226 pending_read: None,
227 pending_write: None,
228 reads: Vec::new(),
229 writes: Vec::new(),
230 }
231 }
232
233 fn complete_read(&mut self, value: u32) {
234 self.pending_read
235 .take()
236 .unwrap()
237 .complete(&value.as_bytes()[..4]);
238 }
239
240 fn complete_read_error(&mut self, error: IoError) {
241 self.pending_read.take().unwrap().complete_error(error);
242 }
243
244 fn complete_write(&mut self) {
245 self.pending_write.take().unwrap().complete();
246 }
247
248 fn complete_write_error(&mut self, error: IoError) {
249 self.pending_write.take().unwrap().complete_error(error);
250 }
251 }
252
253 impl PciBusCfgAccessCallbacks for DeferredCallbacks {
254 fn read(
255 &mut self,
256 addr: PciConfigAddress,
257 mut value: ByteEnabledDwordRead<'_>,
258 ) -> IoResult {
259 self.reads.push(addr);
260 match self.read_action {
261 ReadAction::Ok(read_value) => {
262 value.set(read_value);
263 IoResult::Ok
264 }
265 ReadAction::Err(error) => IoResult::Err(error),
266 ReadAction::Defer => {
267 let (deferred, token) = defer_read();
268 assert!(self.pending_read.replace(deferred).is_none());
269 IoResult::Defer(token)
270 }
271 }
272 }
273
274 fn write(&mut self, addr: PciConfigAddress, value: ByteEnabledDwordWrite) -> IoResult {
275 self.writes.push((addr, value.extract()));
276 match self.write_action {
277 WriteAction::Ok => IoResult::Ok,
278 WriteAction::Err(error) => IoResult::Err(error),
279 WriteAction::Defer => {
280 let (deferred, token) = defer_write();
281 assert!(self.pending_write.replace(deferred).is_none());
282 IoResult::Defer(token)
283 }
284 }
285 }
286 }
287
288 fn poll_once(handler: &mut PciBusCfgAccessHandler) {
289 let mut cx = Context::from_waker(std::task::Waker::noop());
290 handler.poll(&mut cx);
291 }
292
293 fn poll_read_token(token: &mut DeferredToken, bytes: &mut [u8]) -> Poll<Result<(), IoError>> {
294 let mut cx = Context::from_waker(std::task::Waker::noop());
295 token.poll_read(&mut cx, bytes)
296 }
297
298 fn poll_write_token(token: &mut DeferredToken) -> Poll<Result<(), IoError>> {
299 let mut cx = Context::from_waker(std::task::Waker::noop());
300 token.poll_write(&mut cx)
301 }
302
303 #[test]
304 fn immediate_read_applies_byte_enable() {
305 let mut handler = PciBusCfgAccessHandler::new();
306 let mut callbacks = DeferredCallbacks::new(ReadAction::Ok(0x1122_3344), WriteAction::Ok);
307 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
308 let mut buffer = 0xffff_ffff;
309 let value = ByteEnabledDwordRead::new(&mut buffer, PciConfigByteEnable::HIGH_WORD);
310
311 assert!(matches!(
312 handler.read(addr, value, &mut callbacks),
313 IoResult::Ok
314 ));
315 assert_eq!(callbacks.reads, vec![addr]);
316 assert_eq!(buffer, 0x1122_ffff);
317 }
318
319 #[test]
320 fn immediate_read_error_is_returned() {
321 let mut handler = PciBusCfgAccessHandler::new();
322 let mut callbacks =
323 DeferredCallbacks::new(ReadAction::Err(IoError::InvalidRegister), WriteAction::Ok);
324 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
325 let mut buffer = 0;
326 let value = ByteEnabledDwordRead::with_all_bytes_enabled(&mut buffer);
327
328 assert!(matches!(
329 handler.read(addr, value, &mut callbacks),
330 IoResult::Err(IoError::InvalidRegister)
331 ));
332 assert_eq!(callbacks.reads, vec![addr]);
333 }
334
335 #[test]
336 fn deferred_read_applies_byte_enable() {
337 let mut handler = PciBusCfgAccessHandler::new();
338 let mut callbacks = DeferredCallbacks::new(ReadAction::Defer, WriteAction::Ok);
339 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
340 let mut buffer = 0xffff_ffff;
341 let value = ByteEnabledDwordRead::new(&mut buffer, PciConfigByteEnable::HIGH_WORD);
342
343 let IoResult::Defer(mut bus_token) = handler.read(addr, value, &mut callbacks) else {
344 panic!("read should defer");
345 };
346
347 callbacks.complete_read(0x1122_3344);
348 poll_once(&mut handler);
349
350 let mut read_data = [0; 2];
351 assert!(matches!(
352 poll_read_token(&mut bus_token, &mut read_data),
353 Poll::Ready(Ok(()))
354 ));
355
356 assert_eq!(read_data, [0x22, 0x11]);
357 }
358
359 #[test]
360 fn deferred_read_error_completes_outer_read_with_error() {
361 let mut handler = PciBusCfgAccessHandler::new();
362 let mut callbacks = DeferredCallbacks::new(ReadAction::Defer, WriteAction::Ok);
363 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
364 let mut buffer = 0;
365 let value = ByteEnabledDwordRead::with_all_bytes_enabled(&mut buffer);
366
367 let IoResult::Defer(mut bus_token) = handler.read(addr, value, &mut callbacks) else {
368 panic!("read should defer");
369 };
370
371 callbacks.complete_read_error(IoError::NoResponse);
372 poll_once(&mut handler);
373
374 let mut read_data = [0; 4];
375 assert!(matches!(
376 poll_read_token(&mut bus_token, &mut read_data),
377 Poll::Ready(Err(IoError::NoResponse))
378 ));
379 }
380
381 #[test]
382 fn partial_writes_do_not_read_for_write() {
383 let mut handler = PciBusCfgAccessHandler::new();
384 let mut callbacks = DeferredCallbacks::new(ReadAction::Ok(0x1122_3344), WriteAction::Ok);
385 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
386 let write_value = ByteEnabledDwordWrite::new(0xaa00, PciConfigByteEnable::BYTE1);
387
388 assert!(matches!(
389 handler.write(addr, write_value, &mut callbacks),
390 IoResult::Ok
391 ));
392 assert_eq!(callbacks.reads, vec![]);
393 assert_eq!(callbacks.writes, vec![(addr, 0x0000_aa00)]);
394 }
395
396 #[test]
397 fn immediate_write_error_is_returned() {
398 let mut handler = PciBusCfgAccessHandler::new();
399 let mut callbacks = DeferredCallbacks::new(
400 ReadAction::Ok(0x1122_3344),
401 WriteAction::Err(IoError::InvalidRegister),
402 );
403 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
404 let write_value = ByteEnabledDwordWrite::new(0xaa00, PciConfigByteEnable::BYTE1);
405
406 assert!(matches!(
407 handler.write(addr, write_value, &mut callbacks),
408 IoResult::Err(IoError::InvalidRegister)
409 ));
410 assert_eq!(callbacks.writes, vec![(addr, 0x0000_aa00)]);
411 }
412
413 #[test]
414 fn deferred_writes_complete_outer_write() {
415 let mut handler = PciBusCfgAccessHandler::new();
416 let mut callbacks = DeferredCallbacks::new(ReadAction::Ok(0), WriteAction::Defer);
417 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
418 let write_value = ByteEnabledDwordWrite::with_all_bytes_enabled(0xaabb_ccdd);
419
420 let IoResult::Defer(mut bus_token) = handler.write(addr, write_value, &mut callbacks)
421 else {
422 panic!("write should defer");
423 };
424
425 callbacks.complete_write();
426 poll_once(&mut handler);
427
428 assert!(matches!(
429 poll_write_token(&mut bus_token),
430 Poll::Ready(Ok(()))
431 ));
432 }
433
434 #[test]
435 fn deferred_write_error_completes_outer_write_with_error() {
436 let mut handler = PciBusCfgAccessHandler::new();
437 let mut callbacks = DeferredCallbacks::new(ReadAction::Ok(0), WriteAction::Defer);
438 let addr = PciConfigAddress::new(0, 0, 1).unwrap();
439 let write_value = ByteEnabledDwordWrite::with_all_bytes_enabled(0xaabb_ccdd);
440
441 let IoResult::Defer(mut bus_token) = handler.write(addr, write_value, &mut callbacks)
442 else {
443 panic!("write should defer");
444 };
445
446 callbacks.complete_write_error(IoError::NoResponse);
447 poll_once(&mut handler);
448
449 assert!(matches!(
450 poll_write_token(&mut bus_token),
451 Poll::Ready(Err(IoError::NoResponse))
452 ));
453 }
454}