19901addaSAbdiel Janulgue // SPDX-License-Identifier: GPL-2.0 29901addaSAbdiel Janulgue 39901addaSAbdiel Janulgue //! Rust DMA api test (based on QEMU's `pci-testdev`). 49901addaSAbdiel Janulgue //! 59901addaSAbdiel Janulgue //! To make this driver probe, QEMU must be run with `-device pci-testdev`. 69901addaSAbdiel Janulgue 7*2cd5769fSLinus Torvalds use kernel::{bindings, device::Core, dma::CoherentAllocation, pci, prelude::*, types::ARef}; 89901addaSAbdiel Janulgue 99901addaSAbdiel Janulgue struct DmaSampleDriver { 10*2cd5769fSLinus Torvalds pdev: ARef<pci::Device>, 119901addaSAbdiel Janulgue ca: CoherentAllocation<MyStruct>, 129901addaSAbdiel Janulgue } 139901addaSAbdiel Janulgue 149901addaSAbdiel Janulgue const TEST_VALUES: [(u32, u32); 5] = [ 159901addaSAbdiel Janulgue (0xa, 0xb), 169901addaSAbdiel Janulgue (0xc, 0xd), 179901addaSAbdiel Janulgue (0xe, 0xf), 189901addaSAbdiel Janulgue (0xab, 0xba), 199901addaSAbdiel Janulgue (0xcd, 0xef), 209901addaSAbdiel Janulgue ]; 219901addaSAbdiel Janulgue 229901addaSAbdiel Janulgue struct MyStruct { 239901addaSAbdiel Janulgue h: u32, 249901addaSAbdiel Janulgue b: u32, 259901addaSAbdiel Janulgue } 269901addaSAbdiel Janulgue 279901addaSAbdiel Janulgue impl MyStruct { 289901addaSAbdiel Janulgue fn new(h: u32, b: u32) -> Self { 299901addaSAbdiel Janulgue Self { h, b } 309901addaSAbdiel Janulgue } 319901addaSAbdiel Janulgue } 329901addaSAbdiel Janulgue // SAFETY: All bit patterns are acceptable values for `MyStruct`. 339901addaSAbdiel Janulgue unsafe impl kernel::transmute::AsBytes for MyStruct {} 349901addaSAbdiel Janulgue // SAFETY: Instances of `MyStruct` have no uninitialized portions. 359901addaSAbdiel Janulgue unsafe impl kernel::transmute::FromBytes for MyStruct {} 369901addaSAbdiel Janulgue 379901addaSAbdiel Janulgue kernel::pci_device_table!( 389901addaSAbdiel Janulgue PCI_TABLE, 399901addaSAbdiel Janulgue MODULE_PCI_TABLE, 409901addaSAbdiel Janulgue <DmaSampleDriver as pci::Driver>::IdInfo, 419901addaSAbdiel Janulgue [( 429901addaSAbdiel Janulgue pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5), 439901addaSAbdiel Janulgue () 449901addaSAbdiel Janulgue )] 459901addaSAbdiel Janulgue ); 469901addaSAbdiel Janulgue 479901addaSAbdiel Janulgue impl pci::Driver for DmaSampleDriver { 489901addaSAbdiel Janulgue type IdInfo = (); 499901addaSAbdiel Janulgue const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 509901addaSAbdiel Janulgue 51*2cd5769fSLinus Torvalds fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 529901addaSAbdiel Janulgue dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 539901addaSAbdiel Janulgue 549901addaSAbdiel Janulgue let ca: CoherentAllocation<MyStruct> = 559901addaSAbdiel Janulgue CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 569901addaSAbdiel Janulgue 579901addaSAbdiel Janulgue || -> Result { 589901addaSAbdiel Janulgue for (i, value) in TEST_VALUES.into_iter().enumerate() { 599901addaSAbdiel Janulgue kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1)); 609901addaSAbdiel Janulgue } 619901addaSAbdiel Janulgue 629901addaSAbdiel Janulgue Ok(()) 639901addaSAbdiel Janulgue }()?; 649901addaSAbdiel Janulgue 659901addaSAbdiel Janulgue let drvdata = KBox::new( 669901addaSAbdiel Janulgue Self { 67*2cd5769fSLinus Torvalds pdev: pdev.into(), 689901addaSAbdiel Janulgue ca, 699901addaSAbdiel Janulgue }, 709901addaSAbdiel Janulgue GFP_KERNEL, 719901addaSAbdiel Janulgue )?; 729901addaSAbdiel Janulgue 739901addaSAbdiel Janulgue Ok(drvdata.into()) 749901addaSAbdiel Janulgue } 759901addaSAbdiel Janulgue } 769901addaSAbdiel Janulgue 779901addaSAbdiel Janulgue impl Drop for DmaSampleDriver { 789901addaSAbdiel Janulgue fn drop(&mut self) { 799901addaSAbdiel Janulgue dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n"); 809901addaSAbdiel Janulgue 819901addaSAbdiel Janulgue let _ = || -> Result { 829901addaSAbdiel Janulgue for (i, value) in TEST_VALUES.into_iter().enumerate() { 839901addaSAbdiel Janulgue assert_eq!(kernel::dma_read!(self.ca[i].h), value.0); 849901addaSAbdiel Janulgue assert_eq!(kernel::dma_read!(self.ca[i].b), value.1); 859901addaSAbdiel Janulgue } 869901addaSAbdiel Janulgue Ok(()) 879901addaSAbdiel Janulgue }(); 889901addaSAbdiel Janulgue } 899901addaSAbdiel Janulgue } 909901addaSAbdiel Janulgue 919901addaSAbdiel Janulgue kernel::module_pci_driver! { 929901addaSAbdiel Janulgue type: DmaSampleDriver, 939901addaSAbdiel Janulgue name: "rust_dma", 949901addaSAbdiel Janulgue authors: ["Abdiel Janulgue"], 959901addaSAbdiel Janulgue description: "Rust DMA test", 969901addaSAbdiel Janulgue license: "GPL v2", 979901addaSAbdiel Janulgue } 98