1#![deny(missing_docs)]
8
9use arrayvec::ArrayVec;
10use core::fmt::Debug;
11use fidl_fuchsia_driver_framework as fdf;
12use fidl_next::{Request, Responder};
13use fidl_next_fuchsia_hardware_pci::{self as fpci, DeviceServerHandler};
14use fuchsia_async as fasync;
15use fuchsia_component::server::{ServiceFs, ServiceObjTrait};
16use fuchsia_sync::Mutex;
17use std::collections::HashMap;
18use std::mem::size_of;
19use std::sync::Arc;
20
21const BASE_CONFIG_SIZE: usize = 256;
22const CONFIG_HEADER_SIZE: usize = 64;
23const MSI_MAX_VECTORS: u32 = 32;
24const MSIX_MAX_VECTORS: u32 = 8;
25const PCI_EXPRESS_CAPABILITY_SIZE: u8 = 0x3B;
26
27enum Bar {
29 Vmo { size: u64, vmo: zx::Vmo },
30}
31
32impl Bar {
33 fn to_fidl(&self, bar_id: u32) -> Result<fpci::Bar, zx::Status> {
34 match self {
35 Self::Vmo { size, vmo } => {
36 let vmo_dup = vmo.duplicate_handle(zx::Rights::SAME_RIGHTS)?;
37 Ok(fpci::Bar { bar_id, size: *size, result: fpci::BarResult::Vmo(vmo_dup) })
38 }
39 }
40 }
41}
42
43#[derive(Clone, Debug, PartialEq, Eq)]
44struct Capability {
45 id: fpci::CapabilityId,
46 position: u8,
47 size: u8,
48}
49
50struct State {
51 device_info: fpci::DeviceInfo,
52 bus_mastering: Option<bool>,
53 config: Vec<u8>,
54 bars: [Option<Bar>; fpci::MAX_BAR_COUNT as usize],
55 btis: HashMap<u32, zx::Bti>,
56 capabilities: Vec<Capability>,
57 legacy_interrupt: Option<Arc<zx::VirtualInterrupt>>,
58 msi_interrupts: ArrayVec<Arc<zx::VirtualInterrupt>, { MSI_MAX_VECTORS as usize }>,
59 msix_interrupts: ArrayVec<Arc<zx::VirtualInterrupt>, { MSIX_MAX_VECTORS as usize }>,
60 interrupt_mode: fpci::InterruptMode,
61 requested_irq_count: u32,
62 reset_count: u32,
63}
64
65impl State {
66 fn new() -> Self {
67 Self {
68 device_info: fpci::DeviceInfo {
69 vendor_id: 0,
70 device_id: 0,
71 base_class: 0,
72 sub_class: 0,
73 program_interface: 0,
74 revision_id: 0,
75 bus_id: 0,
76 dev_id: 0,
77 func_id: 0,
78 padding: (),
79 },
80 bus_mastering: None,
81 config: vec![0u8; BASE_CONFIG_SIZE],
82 bars: Default::default(),
83 btis: HashMap::new(),
84 capabilities: Vec::new(),
85 legacy_interrupt: None,
86 msi_interrupts: ArrayVec::new(),
87 msix_interrupts: ArrayVec::new(),
88 interrupt_mode: fpci::InterruptMode::Disabled,
89 requested_irq_count: 0,
90 reset_count: 0,
91 }
92 }
93
94 fn write_raw(&mut self, offset: usize, bytes: &[u8]) {
95 self.config[offset..offset + bytes.len()].copy_from_slice(bytes);
96 }
97
98 fn config_slice(&self, offset: u16, length: usize) -> Result<&[u8], zx::Status> {
99 let start = usize::from(offset);
100 let end = start.checked_add(length).ok_or(zx::Status::OUT_OF_RANGE)?;
101 if end > BASE_CONFIG_SIZE {
102 return Err(zx::Status::OUT_OF_RANGE);
103 }
104 Ok(&self.config[start..end])
105 }
106
107 fn config_slice_mut(&mut self, offset: u16, length: usize) -> Result<&mut [u8], zx::Status> {
108 let start = usize::from(offset);
109 let end = start.checked_add(length).ok_or(zx::Status::OUT_OF_RANGE)?;
110 if start < CONFIG_HEADER_SIZE || end > BASE_CONFIG_SIZE {
112 return Err(zx::Status::OUT_OF_RANGE);
113 }
114 Ok(&mut self.config[start..end])
115 }
116
117 fn read_config8(&self, offset: u16) -> Result<u8, zx::Status> {
118 let slice = self.config_slice(offset, size_of::<u8>())?;
119 Ok(slice[0])
120 }
121
122 fn read_config16(&self, offset: u16) -> Result<u16, zx::Status> {
123 let slice = self.config_slice(offset, size_of::<u16>())?;
124 Ok(u16::from_le_bytes(slice.try_into().unwrap()))
125 }
126
127 fn read_config32(&self, offset: u16) -> Result<u32, zx::Status> {
128 let slice = self.config_slice(offset, size_of::<u32>())?;
129 Ok(u32::from_le_bytes(slice.try_into().unwrap()))
130 }
131
132 fn write_config8(&mut self, offset: u16, value: u8) -> Result<(), zx::Status> {
133 let slice = self.config_slice_mut(offset, size_of::<u8>())?;
134 slice[0] = value;
135 Ok(())
136 }
137
138 fn write_config16(&mut self, offset: u16, value: u16) -> Result<(), zx::Status> {
139 let slice = self.config_slice_mut(offset, size_of::<u16>())?;
140 slice.copy_from_slice(&value.to_le_bytes());
141 Ok(())
142 }
143
144 fn write_config32(&mut self, offset: u16, value: u32) -> Result<(), zx::Status> {
145 let slice = self.config_slice_mut(offset, size_of::<u32>())?;
146 slice.copy_from_slice(&value.to_le_bytes());
147 Ok(())
148 }
149
150 fn set_device_info(&mut self, info: fpci::DeviceInfo) {
151 self.device_info = info;
152 self.write_raw(u16::from(fpci::Config::VendorId).into(), &info.vendor_id.to_le_bytes());
153 self.write_raw(u16::from(fpci::Config::DeviceId).into(), &info.device_id.to_le_bytes());
154 self.write_raw(u16::from(fpci::Config::RevisionId).into(), &info.revision_id.to_le_bytes());
155 self.write_raw(
156 u16::from(fpci::Config::ClassCodeBase).into(),
157 &info.base_class.to_le_bytes(),
158 );
159 self.write_raw(u16::from(fpci::Config::ClassCodeSub).into(), &info.sub_class.to_le_bytes());
160 self.write_raw(
161 u16::from(fpci::Config::ClassCodeIntr).into(),
162 &info.program_interface.to_le_bytes(),
163 );
164 }
165
166 fn add_capability(&mut self, capability_id: fpci::CapabilityId, position: u8, size: u8) {
167 assert!(
168 !matches!(capability_id, fpci::CapabilityId::UnknownOrdinal_(_)),
169 "Unknown capability ID is forbidden"
170 );
171 let pos = usize::from(position);
172 let sz = usize::from(size);
173 assert!(
174 pos >= CONFIG_HEADER_SIZE && pos + sz <= BASE_CONFIG_SIZE,
175 "capability must fit the range [0x{CONFIG_HEADER_SIZE:X}, 0x{BASE_CONFIG_SIZE:X}]"
176 );
177
178 for cap in &self.capabilities {
179 let cap_pos = usize::from(cap.position);
180 let cap_sz = usize::from(cap.size);
181 let overlap = (pos < cap_pos + cap_sz) && (pos + sz > cap_pos);
182 assert!(!overlap, "New capability overlaps with a previous capability {cap:?}");
183 }
184
185 let next_ptr = if self.capabilities.is_empty() {
186 usize::from(u16::from(fpci::Config::CapabilitiesPtr))
187 } else {
188 usize::from(self.capabilities.last().unwrap().position) + 1
189 };
190
191 self.write_raw(pos, &[u8::from(capability_id)]);
192 self.write_raw(next_ptr, &[position]);
193
194 self.capabilities.push(Capability { id: capability_id, position, size });
195 self.capabilities.sort_by_key(|c| c.position);
196 }
197
198 fn add_vendor_capability(&mut self, position: u8, size: u8) {
199 assert!(size > 2, "vendor capability must be at least size 3");
200 self.add_capability(fpci::CapabilityId::Vendor, position, size);
201 self.write_raw(usize::from(position) + 2, &[size]);
204 }
205
206 fn add_pci_express_capability(&mut self, position: u8) {
207 self.add_capability(fpci::CapabilityId::PciExpress, position, PCI_EXPRESS_CAPABILITY_SIZE);
208 }
209
210 fn get_capabilities(&self, id: fpci::CapabilityId) -> Vec<u8> {
211 let mut offsets = Vec::new();
212 let mut current_offset: Option<u8> = None;
213
214 while let Some(found_offset) = self.common_capability_search(id, current_offset) {
215 offsets.push(found_offset);
216 current_offset = Some(found_offset);
217 }
218 offsets
219 }
220
221 fn common_capability_search(&self, id: fpci::CapabilityId, offset: Option<u8>) -> Option<u8> {
222 for cap in &self.capabilities {
223 if offset.is_some_and(|off| cap.position <= off) {
224 continue;
225 }
226 if cap.id == id {
227 return Some(cap.position);
228 }
229 }
230 None
231 }
232
233 fn all_mapped_interrupts_freed(&self) -> bool {
234 let legacy = self.legacy_interrupt.as_ref().into_iter();
235 for irq in legacy.chain(self.msi_interrupts.iter()).chain(self.msix_interrupts.iter()) {
236 let info = irq.count_info().expect("get irq info");
237 if info.handle_count > 1 {
240 return false;
241 }
242 }
243 true
244 }
245
246 fn get_interrupt_modes(&self) -> fpci::InterruptModes {
247 let has_legacy = self.legacy_interrupt.is_some();
248 let msi_count = if self.msi_interrupts.is_empty() {
249 0
250 } else if self.msi_interrupts.len() == 1 {
251 1
252 } else {
253 let len = u8::try_from(self.msi_interrupts.len()).unwrap();
254 1 << (7 - len.leading_zeros())
255 };
256 let msix_count = u16::try_from(self.msix_interrupts.len()).unwrap();
257 fpci::InterruptModes { has_legacy, msi_count, msix_count }
258 }
259
260 fn set_interrupt_mode(
261 &mut self,
262 mode: fpci::InterruptMode,
263 requested_irq_count: u32,
264 ) -> Result<(), zx::Status> {
265 if !self.all_mapped_interrupts_freed() {
266 return Err(zx::Status::BAD_STATE);
267 }
268 match mode {
269 fpci::InterruptMode::Disabled => {
270 self.interrupt_mode = mode;
271 self.requested_irq_count = 0;
272 Ok(())
273 }
274 fpci::InterruptMode::Legacy => {
275 if requested_irq_count > 1 {
276 return Err(zx::Status::INVALID_ARGS);
277 }
278 if self.legacy_interrupt.is_none() {
279 return Err(zx::Status::NOT_SUPPORTED);
280 }
281 self.interrupt_mode = mode;
282 self.requested_irq_count = 1;
283 Ok(())
284 }
285 fpci::InterruptMode::Msi => {
286 if self.msi_interrupts.is_empty() {
287 return Err(zx::Status::NOT_SUPPORTED);
288 }
289 if requested_irq_count == 0
290 || !requested_irq_count.is_power_of_two()
291 || requested_irq_count > MSI_MAX_VECTORS
292 {
293 return Err(zx::Status::INVALID_ARGS);
294 }
295 if u32::try_from(self.msi_interrupts.len()).unwrap() < requested_irq_count {
296 return Err(zx::Status::INVALID_ARGS);
297 }
298 self.interrupt_mode = mode;
299 self.requested_irq_count = requested_irq_count;
300 Ok(())
301 }
302 fpci::InterruptMode::MsiX => {
303 if self.msix_interrupts.is_empty() {
304 return Err(zx::Status::NOT_SUPPORTED);
305 }
306 if requested_irq_count == 0 || requested_irq_count > MSIX_MAX_VECTORS {
307 return Err(zx::Status::INVALID_ARGS);
308 }
309 if u32::try_from(self.msix_interrupts.len()).unwrap() < requested_irq_count {
310 return Err(zx::Status::INVALID_ARGS);
311 }
312 self.interrupt_mode = mode;
313 self.requested_irq_count = requested_irq_count;
314 Ok(())
315 }
316 }
317 }
318
319 fn map_interrupt(&self, which_irq: u32) -> Result<zx::Interrupt, zx::Status> {
320 match self.interrupt_mode {
321 fpci::InterruptMode::Legacy => {
322 if which_irq > 0 {
323 return Err(zx::Status::INVALID_ARGS);
324 }
325 let irq = self.legacy_interrupt.as_ref().ok_or(zx::Status::BAD_STATE)?;
326 Ok(zx::Interrupt::from(
327 irq.duplicate_handle(zx::Rights::SAME_RIGHTS)
328 .expect("duplicate irq")
329 .into_handle(),
330 ))
331 }
332 fpci::InterruptMode::Msi => {
333 let which = usize::try_from(which_irq).unwrap();
334 if which >= usize::try_from(self.requested_irq_count).unwrap() {
335 return Err(zx::Status::INVALID_ARGS);
336 }
337 let irq = self.msi_interrupts.get(which).ok_or(zx::Status::INVALID_ARGS)?;
338 Ok(zx::Interrupt::from(
339 irq.duplicate_handle(zx::Rights::SAME_RIGHTS)
340 .expect("duplicate irq")
341 .into_handle(),
342 ))
343 }
344 fpci::InterruptMode::MsiX => {
345 let which = usize::try_from(which_irq).unwrap();
346 if which >= usize::try_from(self.requested_irq_count).unwrap() {
347 return Err(zx::Status::INVALID_ARGS);
348 }
349 let irq = self.msix_interrupts.get(which).ok_or(zx::Status::INVALID_ARGS)?;
350 Ok(zx::Interrupt::from(
351 irq.duplicate_handle(zx::Rights::SAME_RIGHTS)
352 .expect("duplicate irq")
353 .into_handle(),
354 ))
355 }
356 _ => Err(zx::Status::BAD_STATE),
357 }
358 }
359
360 fn ack_interrupt(&self) -> Result<(), zx::Status> {
361 if self.interrupt_mode == fpci::InterruptMode::Legacy {
362 Ok(())
363 } else {
364 Err(zx::Status::BAD_STATE)
365 }
366 }
367}
368
369#[derive(Clone)]
371pub struct FakePci {
372 state: Arc<Mutex<State>>,
373}
374
375impl Default for FakePci {
376 fn default() -> Self {
377 Self::new()
378 }
379}
380
381impl FakePci {
382 pub fn new() -> Self {
384 Self { state: Arc::new(Mutex::new(State::new())) }
385 }
386
387 pub fn set_device_info(&self, info: fpci::DeviceInfo) {
389 self.state.lock().set_device_info(info);
390 }
391
392 pub fn device_info(&self) -> fpci::DeviceInfo {
394 self.state.lock().device_info
395 }
396
397 pub fn bus_master_enabled(&self) -> Option<bool> {
399 self.state.lock().bus_mastering
400 }
401
402 pub fn reset_count(&self) -> u32 {
404 self.state.lock().reset_count
405 }
406
407 pub fn add_vmo_bar(&self, bar_id: u32, size: u64, vmo: zx::Vmo) {
414 assert!(
415 self.state
416 .lock()
417 .bars
418 .get_mut(bar_id as usize)
419 .expect("invalid bar id")
420 .replace(Bar::Vmo { size, vmo })
421 .is_none(),
422 "{bar_id} already set"
423 );
424 }
425
426 pub fn create_vmo_bar(&self, bar_id: u32, size: u64) {
433 self.add_vmo_bar(bar_id, size, zx::Vmo::create(size).unwrap());
434 }
435
436 pub fn vmo_bar(&self, bar_id: u32) -> Option<zx::Vmo> {
438 let state = self.state.lock();
439 let Bar::Vmo { size: _, vmo } =
440 state.bars.get(bar_id as usize).expect("invalid bar id").as_ref()?;
441 Some(vmo.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap())
442 }
443
444 pub fn add_bti(&self, index: u32, bti: zx::Bti) {
450 assert!(self.state.lock().btis.insert(index, bti).is_none());
451 }
452
453 pub fn add_capability(&self, id: fpci::CapabilityId, position: u8, size: u8) {
463 self.state.lock().add_capability(id, position, size);
464 }
465
466 pub fn add_vendor_capability(&self, position: u8, size: u8) {
473 self.state.lock().add_vendor_capability(position, size);
474 }
475
476 pub fn add_pci_express_capability(&self, position: u8) {
482 self.state.lock().add_pci_express_capability(position);
483 }
484
485 pub fn add_legacy_interrupt(&self) -> Arc<zx::VirtualInterrupt> {
492 let virq = Arc::new(
493 zx::VirtualInterrupt::create_virtual().expect("Failed to create virtual interrupt"),
494 );
495 let mut state = self.state.lock();
496 assert!(state.legacy_interrupt.is_none(), "Legacy interrupt already added");
497 state.legacy_interrupt = Some(virq.clone());
498 virq
499 }
500
501 pub fn add_msi_interrupt(&self) -> Arc<zx::VirtualInterrupt> {
510 let virq = Arc::new(
511 zx::VirtualInterrupt::create_virtual().expect("Failed to create virtual interrupt"),
512 );
513 let mut state = self.state.lock();
514 state.msi_interrupts.push(virq.clone());
515 virq
516 }
517
518 pub fn add_msix_interrupt(&self) -> Arc<zx::VirtualInterrupt> {
527 let virq = Arc::new(
528 zx::VirtualInterrupt::create_virtual().expect("Failed to create virtual interrupt"),
529 );
530 let mut state = self.state.lock();
531 state.msix_interrupts.push(virq.clone());
532 virq
533 }
534
535 pub fn interrupt_mode(&self) -> fpci::InterruptMode {
537 self.state.lock().interrupt_mode
538 }
539
540 pub fn requested_irq_count(&self) -> u32 {
542 self.state.lock().requested_irq_count
543 }
544
545 pub fn read_config8(&self, offset: u16) -> u8 {
551 self.state.lock().read_config8(offset).expect("read_config8 failed")
552 }
553
554 pub fn read_config16(&self, offset: u16) -> u16 {
560 self.state.lock().read_config16(offset).expect("read_config16 failed")
561 }
562
563 pub fn read_config32(&self, offset: u16) -> u32 {
569 self.state.lock().read_config32(offset).expect("read_config32 failed")
570 }
571
572 pub fn write_config8(&self, offset: u16, value: u8) {
579 self.state.lock().write_config8(offset, value).expect("write_config8 failed");
580 }
581
582 pub fn write_config16(&self, offset: u16, value: u16) {
589 self.state.lock().write_config16(offset, value).expect("write_config16 failed");
590 }
591
592 pub fn write_config32(&self, offset: u16, value: u32) {
599 self.state.lock().write_config32(offset, value).expect("write_config32 failed");
600 }
601
602 pub fn serve<O: ServiceObjTrait>(
604 &self,
605 service_fs: &mut ServiceFs<O>,
606 scope: fasync::ScopeHandle,
607 instance_name: &str,
608 ) -> fdf::Offer {
609 fdf_component::ServiceOffer::<fpci::Service>::new_next()
610 .add_default_named_next(
611 service_fs,
612 instance_name,
613 Service { state: self.state.clone(), scope },
614 )
615 .build_zircon_offer_next()
616 }
617}
618
619struct Service {
620 state: Arc<Mutex<State>>,
621 scope: fasync::ScopeHandle,
622}
623
624impl fpci::ServiceHandler for Service {
625 fn device(&self, server_end: fidl_next::ServerEnd<fpci::Device>) {
626 server_end.spawn_on(Server { state: self.state.clone() }, &self.scope);
627 }
628}
629
630struct Server {
631 state: Arc<Mutex<State>>,
632}
633
634impl DeviceServerHandler for Server {
635 async fn get_device_info(&mut self, responder: Responder<fpci::device::GetDeviceInfo>) {
636 let info = self.state.lock().device_info;
637 responder.respond(&info).await.expect_respond("get_device_info");
638 }
639
640 async fn get_bar(
641 &mut self,
642 request: Request<fpci::device::GetBar>,
643 responder: Responder<fpci::device::GetBar>,
644 ) {
645 let bar_id = request.payload().bar_id;
646 let result = {
647 let state = self.state.lock();
648 match state.bars.get(bar_id as usize).as_ref() {
649 None => Err(zx::Status::INVALID_ARGS),
650 Some(None) => Err(zx::Status::NOT_FOUND),
651 Some(Some(bar)) => bar.to_fidl(bar_id),
652 }
653 };
654 match result {
655 Ok(bar) => {
656 responder.respond(bar).await.expect_respond("get_bar");
657 }
658 Err(e) => {
659 responder.respond_err(e).await.expect_respond("get_bar");
660 }
661 }
662 }
663
664 async fn set_bus_mastering(
665 &mut self,
666 request: Request<fpci::device::SetBusMastering>,
667 responder: Responder<fpci::device::SetBusMastering>,
668 ) {
669 self.state.lock().bus_mastering = Some(request.payload().enabled);
670 responder.respond(()).await.expect_respond("set_bus_mastering");
671 }
672
673 async fn reset_device(&mut self, responder: Responder<fpci::device::ResetDevice>) {
674 self.state.lock().reset_count += 1;
675 responder.respond(()).await.expect_respond("reset_device");
676 }
677
678 async fn ack_interrupt(&mut self, responder: Responder<fpci::device::AckInterrupt>) {
679 let result = self.state.lock().ack_interrupt();
680 match result {
681 Ok(()) => {
682 responder.respond(()).await.expect_respond("ack_interrupt");
683 }
684 Err(e) => {
685 responder.respond_err(e).await.expect_respond("ack_interrupt");
686 }
687 }
688 }
689
690 async fn map_interrupt(
691 &mut self,
692 request: Request<fpci::device::MapInterrupt>,
693 responder: Responder<fpci::device::MapInterrupt>,
694 ) {
695 let which_irq = request.payload().which_irq;
696 let result = self.state.lock().map_interrupt(which_irq);
697 match result {
698 Ok(interrupt) => {
699 responder.respond(interrupt).await.expect_respond("map_interrupt");
700 }
701 Err(e) => {
702 responder.respond_err(e).await.expect_respond("map_interrupt");
703 }
704 }
705 }
706
707 async fn get_interrupt_modes(&mut self, responder: Responder<fpci::device::GetInterruptModes>) {
708 let modes = self.state.lock().get_interrupt_modes();
709 responder.respond(&modes).await.expect_respond("get_interrupt_modes");
710 }
711
712 async fn set_interrupt_mode(
713 &mut self,
714 request: Request<fpci::device::SetInterruptMode>,
715 responder: Responder<fpci::device::SetInterruptMode>,
716 ) {
717 let payload = request.payload();
718 let result =
719 self.state.lock().set_interrupt_mode(payload.mode, payload.requested_irq_count);
720 match result {
721 Ok(()) => {
722 responder.respond(()).await.expect_respond("set_interrupt_mode");
723 }
724 Err(e) => {
725 responder.respond_err(e).await.expect_respond("set_interrupt_mode");
726 }
727 }
728 }
729
730 async fn read_config8(
731 &mut self,
732 request: Request<fpci::device::ReadConfig8>,
733 responder: Responder<fpci::device::ReadConfig8>,
734 ) {
735 let res = self.state.lock().read_config8(request.payload().offset);
736 match res {
737 Ok(val) => {
738 responder.respond(val).await.expect_respond("read_config8");
739 }
740 Err(e) => {
741 responder.respond_err(e).await.expect_respond("read_config8");
742 }
743 }
744 }
745
746 async fn read_config16(
747 &mut self,
748 request: Request<fpci::device::ReadConfig16>,
749 responder: Responder<fpci::device::ReadConfig16>,
750 ) {
751 let res = self.state.lock().read_config16(request.payload().offset);
752 match res {
753 Ok(val) => {
754 responder.respond(val).await.expect_respond("read_config16");
755 }
756 Err(e) => {
757 responder.respond_err(e).await.expect_respond("read_config16");
758 }
759 }
760 }
761
762 async fn read_config32(
763 &mut self,
764 request: Request<fpci::device::ReadConfig32>,
765 responder: Responder<fpci::device::ReadConfig32>,
766 ) {
767 let res = self.state.lock().read_config32(request.payload().offset);
768 match res {
769 Ok(val) => {
770 responder.respond(val).await.expect_respond("read_config32");
771 }
772 Err(e) => {
773 responder.respond_err(e).await.expect_respond("read_config32");
774 }
775 }
776 }
777
778 async fn write_config8(
779 &mut self,
780 request: Request<fpci::device::WriteConfig8>,
781 responder: Responder<fpci::device::WriteConfig8>,
782 ) {
783 let payload = request.payload();
784 let res = self.state.lock().write_config8(payload.offset, payload.value);
785 match res {
786 Ok(()) => {
787 responder.respond(()).await.expect_respond("write_config8");
788 }
789 Err(e) => {
790 responder.respond_err(e).await.expect_respond("write_config8");
791 }
792 }
793 }
794
795 async fn write_config16(
796 &mut self,
797 request: Request<fpci::device::WriteConfig16>,
798 responder: Responder<fpci::device::WriteConfig16>,
799 ) {
800 let payload = request.payload();
801 let res = self.state.lock().write_config16(payload.offset, payload.value);
802 match res {
803 Ok(()) => {
804 responder.respond(()).await.expect_respond("write_config16");
805 }
806 Err(e) => {
807 responder.respond_err(e).await.expect_respond("write_config16");
808 }
809 }
810 }
811
812 async fn write_config32(
813 &mut self,
814 request: Request<fpci::device::WriteConfig32>,
815 responder: Responder<fpci::device::WriteConfig32>,
816 ) {
817 let payload = request.payload();
818 let res = self.state.lock().write_config32(payload.offset, payload.value);
819 match res {
820 Ok(()) => {
821 responder.respond(()).await.expect_respond("write_config32");
822 }
823 Err(e) => {
824 responder.respond_err(e).await.expect_respond("write_config32");
825 }
826 }
827 }
828
829 async fn get_capabilities(
830 &mut self,
831 request: Request<fpci::device::GetCapabilities>,
832 responder: Responder<fpci::device::GetCapabilities>,
833 ) {
834 let id = request.payload().id;
835 let offsets = self.state.lock().get_capabilities(id);
836 responder.respond(&offsets).await.expect_respond("get_capabilities");
837 }
838
839 async fn get_extended_capabilities(
840 &mut self,
841 _request: Request<fpci::device::GetExtendedCapabilities>,
842 _responder: Responder<fpci::device::GetExtendedCapabilities>,
843 ) {
844 unimplemented!()
845 }
846
847 async fn get_bti(
848 &mut self,
849 request: Request<fpci::device::GetBti>,
850 responder: Responder<fpci::device::GetBti>,
851 ) {
852 let index = request.payload().index;
853 let result = {
854 let state = self.state.lock();
855 if let Some(bti) = state.btis.get(&index) {
856 bti.duplicate_handle(zx::Rights::SAME_RIGHTS)
857 } else {
858 Err(zx::Status::NOT_FOUND)
859 }
860 };
861 match result {
862 Ok(bti) => {
863 responder.respond(bti).await.expect_respond("get_bti");
864 }
865 Err(e) => {
866 responder.respond_err(e).await.expect_respond("get_bti");
867 }
868 }
869 }
870}
871
872trait RespondExt {
873 fn expect_respond(self, msg: &str);
874}
875
876impl<E: Debug> RespondExt for Result<(), fidl_next::Error<E>> {
877 fn expect_respond(self, msg: &str) {
878 self.unwrap_or_else(|e: fidl_next::Error<_>| {
879 match e {
881 fidl_next::Error::Protocol(fidl_next::ProtocolError::PeerClosed) => {}
882 e => {
883 panic!("responding {msg}: {e:?}")
884 }
885 }
886 })
887 }
888}
889
890#[cfg(test)]
891mod tests {
892 use super::*;
893 use fake_bti::FakeBti;
894 use fidl_next::fuchsia::create_channel;
895 use fixture::fixture;
896
897 async fn run_test_with_fake<F, Fut>(_test_name: &str, test_func: F)
898 where
899 F: FnOnce(fidl_next::Client<fpci::Device>, FakePci) -> Fut,
900 Fut: std::future::Future<Output = ()>,
901 {
902 let fake_pci = FakePci::new();
903
904 let (client_end, server_end) = create_channel::<fpci::Device>();
905 let server = Server { state: fake_pci.state.clone() };
906 let scope = fasync::Scope::new_with_name("test");
907 server_end.spawn_on(server, &scope);
908
909 let client = client_end.spawn();
910 test_func(client, fake_pci).await;
911 }
912
913 #[fixture(run_test_with_fake)]
914 #[fuchsia::test]
915 async fn test_get_device_info(client: fidl_next::Client<fpci::Device>, fake_pci: FakePci) {
916 let expected_info = fpci::DeviceInfo {
917 vendor_id: 0x1234,
918 device_id: 0x5678,
919 base_class: 0x01,
920 sub_class: 0x02,
921 program_interface: 0x03,
922 revision_id: 0x04,
923 bus_id: 1,
924 dev_id: 2,
925 func_id: 3,
926 padding: (),
927 };
928 fake_pci.set_device_info(expected_info);
929
930 let res = client.get_device_info().await.expect("Failed to send get_device_info request");
931 assert_eq!(res.info, expected_info);
932
933 assert_eq!(
935 fake_pci.read_config16(u16::from(fpci::Config::VendorId)),
936 expected_info.vendor_id
937 );
938 assert_eq!(
939 fake_pci.read_config16(u16::from(fpci::Config::DeviceId)),
940 expected_info.device_id
941 );
942 assert_eq!(
943 fake_pci.read_config8(u16::from(fpci::Config::RevisionId)),
944 expected_info.revision_id
945 );
946 assert_eq!(
947 fake_pci.read_config8(u16::from(fpci::Config::ClassCodeBase)),
948 expected_info.base_class
949 );
950 assert_eq!(
951 fake_pci.read_config8(u16::from(fpci::Config::ClassCodeSub)),
952 expected_info.sub_class
953 );
954 assert_eq!(
955 fake_pci.read_config8(u16::from(fpci::Config::ClassCodeIntr)),
956 expected_info.program_interface
957 );
958 }
959
960 #[fixture(run_test_with_fake)]
961 #[fuchsia::test]
962 async fn test_get_vmo_bar(client: fidl_next::Client<fpci::Device>, fake_pci: FakePci) {
963 let bar_id = 0;
964 let bar_size = 4096;
965 let vmo = zx::Vmo::create(bar_size).expect("Failed to create VMO");
966 let expected_koid = vmo.koid().expect("Failed to get VMO koid");
967 fake_pci.add_vmo_bar(bar_id, bar_size, vmo);
968
969 let bar_res = client
970 .get_bar(bar_id)
971 .await
972 .expect("Failed to send get_bar request")
973 .expect("get_bar returned error status");
974 let fpci::Bar { bar_id: actual_bar_id, size, result } = bar_res.result;
975 assert_eq!(actual_bar_id, bar_id);
976 assert_eq!(size, bar_size);
977
978 let fpci::BarResult::Vmo(returned_vmo) = result else {
979 panic!("Expected VMO bar result");
980 };
981 assert_eq!(returned_vmo.koid().expect("Failed to get returned VMO koid"), expected_koid);
982
983 let non_existent_bar_id = 1;
984 let err_res = client
985 .get_bar(non_existent_bar_id)
986 .await
987 .expect("Failed to send get_bar request for non-existent BAR");
988 assert_eq!(
989 err_res.expect_err("Expected NOT_FOUND for non-existent BAR"),
990 zx::Status::NOT_FOUND
991 );
992 }
993
994 #[fixture(run_test_with_fake)]
995 #[fuchsia::test]
996 async fn test_set_bus_mastering(client: fidl_next::Client<fpci::Device>, fake_pci: FakePci) {
997 assert_eq!(fake_pci.bus_master_enabled(), None);
998
999 let res =
1000 client.set_bus_mastering(true).await.expect("Failed to send set_bus_mastering request");
1001 assert!(res.is_ok());
1002 assert_eq!(fake_pci.bus_master_enabled(), Some(true));
1003
1004 let res = client
1005 .set_bus_mastering(false)
1006 .await
1007 .expect("Failed to send set_bus_mastering request");
1008 assert!(res.is_ok());
1009 assert_eq!(fake_pci.bus_master_enabled(), Some(false));
1010 }
1011
1012 #[fixture(run_test_with_fake)]
1013 #[fuchsia::test]
1014 async fn test_reset_device(client: fidl_next::Client<fpci::Device>, fake_pci: FakePci) {
1015 assert_eq!(fake_pci.reset_count(), 0);
1016 let res = client.reset_device().await.expect("Failed to send reset_device request");
1017 assert!(res.is_ok());
1018 assert_eq!(fake_pci.reset_count(), 1);
1019 let res = client.reset_device().await.expect("Failed to send reset_device request");
1020 assert!(res.is_ok());
1021 assert_eq!(fake_pci.reset_count(), 2);
1022 }
1023
1024 #[fixture(run_test_with_fake)]
1025 #[fuchsia::test]
1026 async fn test_interrupt_api_and_modes(
1027 client: fidl_next::Client<fpci::Device>,
1028 fake_pci: FakePci,
1029 ) {
1030 let legacy_irq = fake_pci.add_legacy_interrupt();
1031 let msi0 = fake_pci.add_msi_interrupt();
1032 let _msi1 = fake_pci.add_msi_interrupt();
1033 let _msi2 = fake_pci.add_msi_interrupt();
1034 let msix0 = fake_pci.add_msix_interrupt();
1035
1036 let modes_res =
1038 client.get_interrupt_modes().await.expect("Failed to send get_interrupt_modes request");
1039 let fpci::DeviceGetInterruptModesResponse { modes } = modes_res;
1040 assert!(modes.has_legacy);
1041 assert_eq!(modes.msi_count, 2);
1042 assert_eq!(modes.msix_count, 1);
1043
1044 let res = client
1046 .set_interrupt_mode(fpci::InterruptMode::Legacy, 1)
1047 .await
1048 .expect("Set legacy interrupt mode failed");
1049 assert!(res.is_ok());
1050 assert_eq!(fake_pci.interrupt_mode(), fpci::InterruptMode::Legacy);
1051
1052 let ack_res = client.ack_interrupt().await.expect("ack_interrupt failed");
1054 assert!(ack_res.is_ok());
1055
1056 let map_res = client.map_interrupt(0).await.expect("map_interrupt failed");
1058 let mapped = map_res.expect("map_interrupt error status").interrupt;
1059 assert_eq!(mapped.koid().unwrap(), legacy_irq.koid().unwrap());
1060
1061 let bad_state_res = client
1063 .set_interrupt_mode(fpci::InterruptMode::Msi, 2)
1064 .await
1065 .expect("set_interrupt_mode failed");
1066 assert_eq!(bad_state_res.unwrap_err(), zx::Status::BAD_STATE);
1067
1068 std::mem::drop(mapped);
1070 let set_msi_res = client
1071 .set_interrupt_mode(fpci::InterruptMode::Msi, 2)
1072 .await
1073 .expect("set_interrupt_mode failed");
1074 assert!(set_msi_res.is_ok());
1075
1076 let ack_err = client.ack_interrupt().await.expect("ack_interrupt failed");
1078 assert_eq!(ack_err.unwrap_err(), zx::Status::BAD_STATE);
1079
1080 let map_msi = client.map_interrupt(0).await.expect("map_interrupt failed");
1082 let mapped_msi = map_msi.expect("mapped msi").interrupt;
1083 assert_eq!(mapped_msi.koid().unwrap(), msi0.koid().unwrap());
1084
1085 std::mem::drop(mapped_msi);
1087 let set_msix_res = client
1088 .set_interrupt_mode(fpci::InterruptMode::MsiX, 1)
1089 .await
1090 .expect("set_interrupt_mode failed");
1091 assert_eq!(set_msix_res, Ok(()));
1092
1093 let map_msix =
1094 client.map_interrupt(0).await.expect("map_interrupt failed").expect("mapped msix");
1095 assert_eq!(map_msix.interrupt.koid().unwrap(), msix0.koid().unwrap());
1096 }
1097
1098 #[fixture(run_test_with_fake)]
1099 #[fuchsia::test]
1100 async fn test_config_space_bounds_and_header_protection(
1101 client: fidl_next::Client<fpci::Device>,
1102 fake_pci: FakePci,
1103 ) {
1104 let r8 = client.read_config8(0).await.expect("read_config8");
1106 assert!(r8.is_ok());
1107
1108 let w8_header = client.write_config8(0, 0xff).await.expect("write_config8");
1110 assert_eq!(w8_header.unwrap_err(), zx::Status::OUT_OF_RANGE);
1111
1112 let w16_header = client.write_config16(0x3e, 0xffff).await.expect("write_config16");
1113 assert_eq!(w16_header.unwrap_err(), zx::Status::OUT_OF_RANGE);
1114
1115 let w8_valid = client.write_config8(0x40, 0xab).await.expect("write_config8");
1117 assert!(w8_valid.is_ok());
1118 assert_eq!(fake_pci.read_config8(0x40), 0xab);
1119
1120 let r8_valid = client.read_config8(0x40).await.expect("read_config8");
1121 assert_eq!(r8_valid.unwrap().value, 0xab);
1122
1123 let r_oob = client.read_config8(256).await.expect("read_config8");
1125 assert_eq!(r_oob.unwrap_err(), zx::Status::OUT_OF_RANGE);
1126
1127 let w_oob = client.write_config8(256, 0x12).await.expect("write_config8");
1128 assert_eq!(w_oob.unwrap_err(), zx::Status::OUT_OF_RANGE);
1129 }
1130
1131 #[fixture(run_test_with_fake)]
1132 #[fuchsia::test]
1133 async fn test_capabilities_chain_and_search(
1134 client: fidl_next::Client<fpci::Device>,
1135 fake_pci: FakePci,
1136 ) {
1137 let pos1 = 0x50;
1138 let pos2 = 0x60;
1139 let pos3 = 0x70;
1140 fake_pci.add_vendor_capability(pos1, 6);
1141 fake_pci.add_vendor_capability(pos2, 8);
1142 fake_pci.add_pci_express_capability(pos3);
1143
1144 assert_eq!(fake_pci.read_config8(u16::from(fpci::Config::CapabilitiesPtr)), pos1);
1145 assert_eq!(fake_pci.read_config8((pos1 + 1).into()), pos2);
1146 assert_eq!(fake_pci.read_config8((pos2 + 1).into()), pos3);
1147
1148 let res_vendor =
1149 client.get_capabilities(fpci::CapabilityId::Vendor).await.expect("get_capabilities");
1150 assert_eq!(res_vendor.offsets, vec![pos1, pos2]);
1151
1152 let res_pcie = client
1153 .get_capabilities(fpci::CapabilityId::PciExpress)
1154 .await
1155 .expect("get_capabilities");
1156 assert_eq!(res_pcie.offsets, vec![pos3]);
1157 }
1158
1159 #[fuchsia::test(logging = false)]
1160 #[should_panic]
1161 fn test_add_capability_unknown_forbidden() {
1162 let fake = FakePci::new();
1163 fake.add_capability(fpci::CapabilityId::UnknownOrdinal_(0x99), 0x50, 6);
1164 }
1165
1166 #[fuchsia::test(logging = false)]
1167 #[should_panic]
1168 fn test_add_capability_overlap_panics() {
1169 let fake = FakePci::new();
1170 fake.add_capability(fpci::CapabilityId::Vendor, 0x50, 8);
1171 fake.add_capability(fpci::CapabilityId::PciExpress, 0x54, 8);
1172 }
1173
1174 #[fuchsia::test(logging = false)]
1175 #[should_panic]
1176 fn test_fake_pci_read_oob_panics() {
1177 let fake = FakePci::new();
1178 let _: u8 = fake.read_config8(256);
1179 }
1180
1181 #[fuchsia::test(logging = false)]
1182 #[should_panic]
1183 fn test_fake_pci_write_header_panics() {
1184 let fake = FakePci::new();
1185 fake.write_config8(0x10, 0xff);
1186 }
1187
1188 #[fuchsia::test(logging = false)]
1189 fn test_vmo_bar_readback_and_nonexistent() {
1190 let fake = FakePci::new();
1191 assert!(fake.vmo_bar(0).is_none());
1192
1193 fake.create_vmo_bar(0, 4096);
1194 let vmo = fake.vmo_bar(0).expect("Expected VMO for bar 0");
1195 assert_eq!(vmo.get_size().unwrap(), 4096);
1196
1197 assert!(fake.vmo_bar(1).is_none());
1198 }
1199
1200 #[fuchsia::test(logging = false)]
1201 #[should_panic]
1202 fn test_duplicate_add_vmo_bar() {
1203 let fake = FakePci::new();
1204 fake.create_vmo_bar(0, 4096);
1205 fake.create_vmo_bar(0, 4096);
1206 }
1207
1208 #[fuchsia::test(logging = false)]
1209 #[should_panic]
1210 fn test_duplicate_add_bti() {
1211 let fake = FakePci::new();
1212 let bti1 = FakeBti::create().expect("Failed to create FakeBti");
1213 let bti2 = FakeBti::create().expect("Failed to create FakeBti");
1214 fake.add_bti(
1215 0,
1216 bti1.duplicate_handle(zx::Rights::SAME_RIGHTS).expect("Failed to duplicate BTI"),
1217 );
1218 fake.add_bti(
1219 0,
1220 bti2.duplicate_handle(zx::Rights::SAME_RIGHTS).expect("Failed to duplicate BTI"),
1221 );
1222 }
1223}