1use crate::{
8 bindings, device,
9 devres::Devres,
10 drm,
11 error::{to_result, Result},
12 prelude::*,
13 str::CStr,
14 types::ARef,
15};
16use macros::vtable;
17
18pub(crate) const FEAT_GEM: u32 = bindings::drm_driver_feature_DRIVER_GEM;
20
21pub struct DriverInfo {
23 pub major: i32,
25 pub minor: i32,
27 pub patchlevel: i32,
29 pub name: &'static CStr,
31 pub desc: &'static CStr,
33}
34
35pub struct AllocOps {
37 pub(crate) gem_create_object: Option<
38 unsafe extern "C" fn(
39 dev: *mut bindings::drm_device,
40 size: usize,
41 ) -> *mut bindings::drm_gem_object,
42 >,
43 pub(crate) prime_handle_to_fd: Option<
44 unsafe extern "C" fn(
45 dev: *mut bindings::drm_device,
46 file_priv: *mut bindings::drm_file,
47 handle: u32,
48 flags: u32,
49 prime_fd: *mut core::ffi::c_int,
50 ) -> core::ffi::c_int,
51 >,
52 pub(crate) prime_fd_to_handle: Option<
53 unsafe extern "C" fn(
54 dev: *mut bindings::drm_device,
55 file_priv: *mut bindings::drm_file,
56 prime_fd: core::ffi::c_int,
57 handle: *mut u32,
58 ) -> core::ffi::c_int,
59 >,
60 pub(crate) gem_prime_import: Option<
61 unsafe extern "C" fn(
62 dev: *mut bindings::drm_device,
63 dma_buf: *mut bindings::dma_buf,
64 ) -> *mut bindings::drm_gem_object,
65 >,
66 pub(crate) gem_prime_import_sg_table: Option<
67 unsafe extern "C" fn(
68 dev: *mut bindings::drm_device,
69 attach: *mut bindings::dma_buf_attachment,
70 sgt: *mut bindings::sg_table,
71 ) -> *mut bindings::drm_gem_object,
72 >,
73 pub(crate) dumb_create: Option<
74 unsafe extern "C" fn(
75 file_priv: *mut bindings::drm_file,
76 dev: *mut bindings::drm_device,
77 args: *mut bindings::drm_mode_create_dumb,
78 ) -> core::ffi::c_int,
79 >,
80 pub(crate) dumb_map_offset: Option<
81 unsafe extern "C" fn(
82 file_priv: *mut bindings::drm_file,
83 dev: *mut bindings::drm_device,
84 handle: u32,
85 offset: *mut u64,
86 ) -> core::ffi::c_int,
87 >,
88}
89
90pub trait AllocImpl: super::private::Sealed + drm::gem::IntoGEMObject {
92 const ALLOC_OPS: AllocOps;
94}
95
96#[vtable]
101pub trait Driver {
102 type Data: Sync + Send;
104
105 type Object: AllocImpl;
107
108 type File: drm::file::DriverFile;
110
111 const INFO: DriverInfo;
113
114 const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
116}
117
118pub struct Registration<T: Driver>(ARef<drm::Device<T>>);
122
123impl<T: Driver> Registration<T> {
124 fn new(drm: &drm::Device<T>, flags: usize) -> Result<Self> {
126 to_result(unsafe { bindings::drm_dev_register(drm.as_raw(), flags) })?;
128
129 Ok(Self(drm.into()))
130 }
131
132 pub fn new_foreign_owned(
135 drm: &drm::Device<T>,
136 dev: &device::Device<device::Bound>,
137 flags: usize,
138 ) -> Result {
139 if drm.as_ref().as_raw() != dev.as_raw() {
140 return Err(EINVAL);
141 }
142
143 let reg = Registration::<T>::new(drm, flags)?;
144 Devres::new_foreign_owned(dev, reg, GFP_KERNEL)
145 }
146
147 pub fn device(&self) -> &drm::Device<T> {
149 &self.0
150 }
151}
152
153unsafe impl<T: Driver> Sync for Registration<T> {}
156
157unsafe impl<T: Driver> Send for Registration<T> {}
159
160impl<T: Driver> Drop for Registration<T> {
161 fn drop(&mut self) {
162 unsafe { bindings::drm_dev_unregister(self.0.as_raw()) };
165 }
166}