Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/rust/rust_driver_auxiliary.rs
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Rust auxiliary driver sample (based on a PCI driver for QEMU's `pci-testdev`).
4
//!
5
//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
6
7
use kernel::{
8
auxiliary, bindings, c_str, device::Core, driver, error::Error, pci, prelude::*, InPlaceModule,
9
};
10
11
use pin_init::PinInit;
12
13
const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
14
const AUXILIARY_NAME: &CStr = c_str!("auxiliary");
15
16
struct AuxiliaryDriver;
17
18
kernel::auxiliary_device_table!(
19
AUX_TABLE,
20
MODULE_AUX_TABLE,
21
<AuxiliaryDriver as auxiliary::Driver>::IdInfo,
22
[(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
23
);
24
25
impl auxiliary::Driver for AuxiliaryDriver {
26
type IdInfo = ();
27
28
const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
29
30
fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
31
dev_info!(
32
adev.as_ref(),
33
"Probing auxiliary driver for auxiliary device with id={}\n",
34
adev.id()
35
);
36
37
ParentDriver::connect(adev)?;
38
39
let this = KBox::new(Self, GFP_KERNEL)?;
40
41
Ok(this.into())
42
}
43
}
44
45
struct ParentDriver {
46
_reg: [auxiliary::Registration; 2],
47
}
48
49
kernel::pci_device_table!(
50
PCI_TABLE,
51
MODULE_PCI_TABLE,
52
<ParentDriver as pci::Driver>::IdInfo,
53
[(
54
pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5),
55
()
56
)]
57
);
58
59
impl pci::Driver for ParentDriver {
60
type IdInfo = ();
61
62
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
63
64
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
65
let this = KBox::new(
66
Self {
67
_reg: [
68
auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?,
69
auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?,
70
],
71
},
72
GFP_KERNEL,
73
)?;
74
75
Ok(this.into())
76
}
77
}
78
79
impl ParentDriver {
80
fn connect(adev: &auxiliary::Device) -> Result<()> {
81
let parent = adev.parent().ok_or(EINVAL)?;
82
let pdev: &pci::Device = parent.try_into()?;
83
84
dev_info!(
85
adev.as_ref(),
86
"Connect auxiliary {} with parent: VendorID={:#x}, DeviceID={:#x}\n",
87
adev.id(),
88
pdev.vendor_id(),
89
pdev.device_id()
90
);
91
92
Ok(())
93
}
94
}
95
96
#[pin_data]
97
struct SampleModule {
98
#[pin]
99
_pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
100
#[pin]
101
_aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
102
}
103
104
impl InPlaceModule for SampleModule {
105
fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
106
try_pin_init!(Self {
107
_pci_driver <- driver::Registration::new(MODULE_NAME, module),
108
_aux_driver <- driver::Registration::new(MODULE_NAME, module),
109
})
110
}
111
}
112
113
module! {
114
type: SampleModule,
115
name: "rust_driver_auxiliary",
116
authors: ["Danilo Krummrich"],
117
description: "Rust auxiliary driver",
118
license: "GPL v2",
119
}
120
121