Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/rust/rust_driver_auxiliary.rs
48999 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,
9
device::{Bound, Core},
10
devres::Devres,
11
driver,
12
error::Error,
13
pci,
14
prelude::*,
15
InPlaceModule,
16
};
17
18
use core::any::TypeId;
19
use pin_init::PinInit;
20
21
const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
22
const AUXILIARY_NAME: &CStr = c_str!("auxiliary");
23
24
struct AuxiliaryDriver;
25
26
kernel::auxiliary_device_table!(
27
AUX_TABLE,
28
MODULE_AUX_TABLE,
29
<AuxiliaryDriver as auxiliary::Driver>::IdInfo,
30
[(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
31
);
32
33
impl auxiliary::Driver for AuxiliaryDriver {
34
type IdInfo = ();
35
36
const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
37
38
fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
39
dev_info!(
40
adev.as_ref(),
41
"Probing auxiliary driver for auxiliary device with id={}\n",
42
adev.id()
43
);
44
45
ParentDriver::connect(adev)?;
46
47
Ok(Self)
48
}
49
}
50
51
#[pin_data]
52
struct ParentDriver {
53
private: TypeId,
54
#[pin]
55
_reg0: Devres<auxiliary::Registration>,
56
#[pin]
57
_reg1: Devres<auxiliary::Registration>,
58
}
59
60
kernel::pci_device_table!(
61
PCI_TABLE,
62
MODULE_PCI_TABLE,
63
<ParentDriver as pci::Driver>::IdInfo,
64
[(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
65
);
66
67
impl pci::Driver for ParentDriver {
68
type IdInfo = ();
69
70
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
71
72
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
73
try_pin_init!(Self {
74
private: TypeId::of::<Self>(),
75
_reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME),
76
_reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME),
77
})
78
}
79
}
80
81
impl ParentDriver {
82
fn connect(adev: &auxiliary::Device<Bound>) -> Result {
83
let dev = adev.parent();
84
let pdev: &pci::Device<Bound> = dev.try_into()?;
85
let drvdata = dev.drvdata::<Self>()?;
86
87
dev_info!(
88
dev,
89
"Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
90
adev.id(),
91
pdev.vendor_id(),
92
pdev.device_id()
93
);
94
95
dev_info!(
96
dev,
97
"We have access to the private data of {:?}.\n",
98
drvdata.private
99
);
100
101
Ok(())
102
}
103
}
104
105
#[pin_data]
106
struct SampleModule {
107
#[pin]
108
_pci_driver: driver::Registration<pci::Adapter<ParentDriver>>,
109
#[pin]
110
_aux_driver: driver::Registration<auxiliary::Adapter<AuxiliaryDriver>>,
111
}
112
113
impl InPlaceModule for SampleModule {
114
fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> {
115
try_pin_init!(Self {
116
_pci_driver <- driver::Registration::new(MODULE_NAME, module),
117
_aux_driver <- driver::Registration::new(MODULE_NAME, module),
118
})
119
}
120
}
121
122
module! {
123
type: SampleModule,
124
name: "rust_driver_auxiliary",
125
authors: ["Danilo Krummrich"],
126
description: "Rust auxiliary driver",
127
license: "GPL v2",
128
}
129
130