rust_driver_auxiliary.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // SPDX-License-Identifier: GPL-2.0
  2. //! Rust auxiliary driver sample (based on a PCI driver for QEMU's `pci-testdev`).
  3. //!
  4. //! To make this driver probe, QEMU must be run with `-device pci-testdev`.
  5. use kernel::{
  6. auxiliary,
  7. device::{
  8. Bound,
  9. Core, //
  10. },
  11. devres::Devres,
  12. driver,
  13. pci,
  14. prelude::*,
  15. InPlaceModule, //
  16. };
  17. use core::any::TypeId;
  18. const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
  19. const AUXILIARY_NAME: &CStr = c"auxiliary";
  20. struct AuxiliaryDriver;
  21. kernel::auxiliary_device_table!(
  22. AUX_TABLE,
  23. MODULE_AUX_TABLE,
  24. <AuxiliaryDriver as auxiliary::Driver>::IdInfo,
  25. [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
  26. );
  27. impl auxiliary::Driver for AuxiliaryDriver {
  28. type IdInfo = ();
  29. const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
  30. fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
  31. dev_info!(
  32. adev,
  33. "Probing auxiliary driver for auxiliary device with id={}\n",
  34. adev.id()
  35. );
  36. ParentDriver::connect(adev)?;
  37. Ok(Self)
  38. }
  39. }
  40. #[pin_data]
  41. struct ParentDriver {
  42. private: TypeId,
  43. #[pin]
  44. _reg0: Devres<auxiliary::Registration>,
  45. #[pin]
  46. _reg1: Devres<auxiliary::Registration>,
  47. }
  48. kernel::pci_device_table!(
  49. PCI_TABLE,
  50. MODULE_PCI_TABLE,
  51. <ParentDriver as pci::Driver>::IdInfo,
  52. [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
  53. );
  54. impl pci::Driver for ParentDriver {
  55. type IdInfo = ();
  56. const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
  57. fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
  58. try_pin_init!(Self {
  59. private: TypeId::of::<Self>(),
  60. _reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME),
  61. _reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME),
  62. })
  63. }
  64. }
  65. impl ParentDriver {
  66. fn connect(adev: &auxiliary::Device<Bound>) -> Result {
  67. let dev = adev.parent();
  68. let pdev: &pci::Device<Bound> = dev.try_into()?;
  69. let drvdata = dev.drvdata::<Self>()?;
  70. dev_info!(
  71. dev,
  72. "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
  73. adev.id(),
  74. pdev.vendor_id(),
  75. pdev.device_id()
  76. );
  77. dev_info!(
  78. dev,
  79. "We have access to the private data of {:?}.\n",
  80. drvdata.private
  81. );
  82. Ok(())
  83. }
  84. }
  85. #[pin_data]
  86. struct SampleModule {
  87. #[pin]
  88. _pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
  89. #[pin]
  90. _aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
  91. }
  92. impl InPlaceModule for SampleModule {
  93. fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
  94. try_pin_init!(Self {
  95. _pci_driver <- driver::Registration::new(MODULE_NAME, module),
  96. _aux_driver <- driver::Registration::new(MODULE_NAME, module),
  97. })
  98. }
  99. }
  100. module! {
  101. type: SampleModule,
  102. name: "rust_driver_auxiliary",
  103. authors: ["Danilo Krummrich"],
  104. description: "Rust auxiliary driver",
  105. license: "GPL v2",
  106. }