Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/rust/rust_driver_auxiliary.rs
29266 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, 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
[(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
54
);
55
56
impl pci::Driver for ParentDriver {
57
type IdInfo = ();
58
59
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
60
61
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
62
let this = KBox::new(
63
Self {
64
_reg: [
65
auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?,
66
auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?,
67
],
68
},
69
GFP_KERNEL,
70
)?;
71
72
Ok(this.into())
73
}
74
}
75
76
impl ParentDriver {
77
fn connect(adev: &auxiliary::Device) -> Result<()> {
78
let parent = adev.parent().ok_or(EINVAL)?;
79
let pdev: &pci::Device = parent.try_into()?;
80
81
let vendor = pdev.vendor_id();
82
dev_info!(
83
adev.as_ref(),
84
"Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
85
adev.id(),
86
vendor,
87
pdev.device_id()
88
);
89
90
Ok(())
91
}
92
}
93
94
#[pin_data]
95
struct SampleModule {
96
#[pin]
97
_pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
98
#[pin]
99
_aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
100
}
101
102
impl InPlaceModule for SampleModule {
103
fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
104
try_pin_init!(Self {
105
_pci_driver <- driver::Registration::new(MODULE_NAME, module),
106
_aux_driver <- driver::Registration::new(MODULE_NAME, module),
107
})
108
}
109
}
110
111
module! {
112
type: SampleModule,
113
name: "rust_driver_auxiliary",
114
authors: ["Danilo Krummrich"],
115
description: "Rust auxiliary driver",
116
license: "GPL v2",
117
}
118
119