1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Rust DMA api test (based on QEMU's `pci-testdev`). 4 //! 5 //! To make this driver probe, QEMU must be run with `-device pci-testdev`. 6 7 use kernel::{bindings, device::Core, dma::CoherentAllocation, pci, prelude::*, types::ARef}; 8 9 struct DmaSampleDriver { 10 pdev: ARef<pci::Device>, 11 ca: CoherentAllocation<MyStruct>, 12 } 13 14 const TEST_VALUES: [(u32, u32); 5] = [ 15 (0xa, 0xb), 16 (0xc, 0xd), 17 (0xe, 0xf), 18 (0xab, 0xba), 19 (0xcd, 0xef), 20 ]; 21 22 struct MyStruct { 23 h: u32, 24 b: u32, 25 } 26 27 impl MyStruct { new(h: u32, b: u32) -> Self28 fn new(h: u32, b: u32) -> Self { 29 Self { h, b } 30 } 31 } 32 // SAFETY: All bit patterns are acceptable values for `MyStruct`. 33 unsafe impl kernel::transmute::AsBytes for MyStruct {} 34 // SAFETY: Instances of `MyStruct` have no uninitialized portions. 35 unsafe impl kernel::transmute::FromBytes for MyStruct {} 36 37 kernel::pci_device_table!( 38 PCI_TABLE, 39 MODULE_PCI_TABLE, 40 <DmaSampleDriver as pci::Driver>::IdInfo, 41 [( 42 pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5), 43 () 44 )] 45 ); 46 47 impl pci::Driver for DmaSampleDriver { 48 type IdInfo = (); 49 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 50 probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>51 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 52 dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 53 54 let ca: CoherentAllocation<MyStruct> = 55 CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 56 57 || -> Result { 58 for (i, value) in TEST_VALUES.into_iter().enumerate() { 59 kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1)); 60 } 61 62 Ok(()) 63 }()?; 64 65 let drvdata = KBox::new( 66 Self { 67 pdev: pdev.into(), 68 ca, 69 }, 70 GFP_KERNEL, 71 )?; 72 73 Ok(drvdata.into()) 74 } 75 } 76 77 impl Drop for DmaSampleDriver { drop(&mut self)78 fn drop(&mut self) { 79 dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n"); 80 81 let _ = || -> Result { 82 for (i, value) in TEST_VALUES.into_iter().enumerate() { 83 assert_eq!(kernel::dma_read!(self.ca[i].h), value.0); 84 assert_eq!(kernel::dma_read!(self.ca[i].b), value.1); 85 } 86 Ok(()) 87 }(); 88 } 89 } 90 91 kernel::module_pci_driver! { 92 type: DmaSampleDriver, 93 name: "rust_dma", 94 authors: ["Abdiel Janulgue"], 95 description: "Rust DMA test", 96 license: "GPL v2", 97 } 98