8
8
9
9
use crate :: {
10
10
bindings, device, driver,
11
- error:: { from_result, to_result, Result } ,
11
+ error:: { from_result, to_result, Error , Result } ,
12
+ io_mem:: Resource ,
13
+ irq,
12
14
str:: CStr ,
13
15
types:: ForeignOwnable ,
14
16
ThisModule ,
15
17
} ;
18
+ use core:: fmt;
16
19
17
20
/// An adapter for the registration of PCI drivers.
18
21
pub struct Adapter < T : Driver > ( T ) ;
@@ -177,6 +180,7 @@ macro_rules! define_pci_id_table {
177
180
} ;
178
181
} ;
179
182
}
183
+ pub use define_pci_id_table;
180
184
181
185
/// A PCI driver
182
186
pub trait Driver {
@@ -187,7 +191,9 @@ pub trait Driver {
187
191
///
188
192
/// Require that `Data` implements `ForeignOwnable`. We guarantee to
189
193
/// never move the underlying wrapped data structure. This allows
190
- type Data : ForeignOwnable + Send + Sync + driver:: DeviceRemoval = ( ) ;
194
+ // TODO: Data Send + Sync ?
195
+ //type Data: ForeignOwnable + Send + Sync + driver::DeviceRemoval = ();
196
+ type Data : ForeignOwnable + driver:: DeviceRemoval = ( ) ;
191
197
192
198
/// The type holding information about each device id supported by the driver.
193
199
type IdInfo : ' static = ( ) ;
@@ -215,11 +221,131 @@ pub trait Driver {
215
221
/// The field `ptr` is non-null and valid for the lifetime of the object.
216
222
pub struct Device {
217
223
ptr : * mut bindings:: pci_dev ,
224
+ res_taken : u64 ,
218
225
}
219
226
220
227
impl Device {
221
- unsafe fn from_ptr ( ptr : * mut bindings:: pci_dev ) -> Self {
222
- Self { ptr }
228
+ pub unsafe fn from_ptr ( ptr : * mut bindings:: pci_dev ) -> Self {
229
+ Self { ptr, res_taken : 0 }
230
+ }
231
+
232
+ pub unsafe fn as_ptr ( & self ) -> * mut bindings:: pci_dev {
233
+ self . ptr
234
+ }
235
+
236
+ pub fn enable_device_mem ( & self ) -> Result {
237
+ let ret = unsafe { bindings:: pci_enable_device_mem ( self . ptr ) } ;
238
+ if ret != 0 {
239
+ Err ( Error :: from_errno ( ret) )
240
+ } else {
241
+ Ok ( ( ) )
242
+ }
243
+ }
244
+
245
+ pub fn set_master ( & self ) {
246
+ unsafe { bindings:: pci_set_master ( self . ptr ) } ;
247
+ }
248
+
249
+ pub fn select_bars ( & self , flags : core:: ffi:: c_ulong ) -> i32 {
250
+ unsafe { bindings:: pci_select_bars ( self . ptr , flags) }
251
+ }
252
+
253
+ pub fn request_selected_regions ( & self , bars : i32 , name : & ' static CStr ) -> Result {
254
+ let ret =
255
+ unsafe { bindings:: pci_request_selected_regions ( self . ptr , bars, name. as_char_ptr ( ) ) } ;
256
+ if ret != 0 {
257
+ Err ( Error :: from_errno ( ret) )
258
+ } else {
259
+ Ok ( ( ) )
260
+ }
261
+ }
262
+
263
+ pub fn take_resource ( & mut self , index : usize ) -> Option < Resource > {
264
+ let pdev = unsafe { & * self . ptr } ;
265
+
266
+ // Fail if the index is beyond the end or if it has already been taken.
267
+ if index >= pdev. resource . len ( ) || self . res_taken & ( 1 << index) != 0 {
268
+ return None ;
269
+ }
270
+
271
+ self . res_taken |= 1 << index;
272
+ Resource :: new ( pdev. resource [ index] . start , pdev. resource [ index] . end )
273
+ }
274
+
275
+ pub fn irq ( & self ) -> Option < u32 > {
276
+ let pdev = unsafe { & * self . ptr } ;
277
+
278
+ if pdev. irq == 0 {
279
+ None
280
+ } else {
281
+ Some ( pdev. irq )
282
+ }
283
+ }
284
+
285
+ pub fn alloc_irq_vectors ( & mut self , min_vecs : u32 , max_vecs : u32 , flags : u32 ) -> Result < u32 > {
286
+ let ret = unsafe {
287
+ bindings:: pci_alloc_irq_vectors_affinity (
288
+ self . ptr ,
289
+ min_vecs,
290
+ max_vecs,
291
+ flags,
292
+ core:: ptr:: null_mut ( ) ,
293
+ )
294
+ } ;
295
+ if ret < 0 {
296
+ Err ( Error :: from_errno ( ret) )
297
+ } else {
298
+ Ok ( ret as _ )
299
+ }
300
+ }
301
+
302
+ pub fn alloc_irq_vectors_affinity (
303
+ & mut self ,
304
+ min_vecs : u32 ,
305
+ max_vecs : u32 ,
306
+ pre : u32 ,
307
+ post : u32 ,
308
+ flags : u32 ,
309
+ ) -> Result < u32 > {
310
+ let mut affd = bindings:: irq_affinity {
311
+ pre_vectors : pre,
312
+ post_vectors : post,
313
+ ..bindings:: irq_affinity:: default ( )
314
+ } ;
315
+
316
+ let ret = unsafe {
317
+ bindings:: pci_alloc_irq_vectors_affinity (
318
+ self . ptr ,
319
+ min_vecs,
320
+ max_vecs,
321
+ flags | bindings:: PCI_IRQ_AFFINITY ,
322
+ & mut affd,
323
+ )
324
+ } ;
325
+ if ret < 0 {
326
+ Err ( Error :: from_errno ( ret) )
327
+ } else {
328
+ Ok ( ret as _ )
329
+ }
330
+ }
331
+
332
+ pub fn free_irq_vectors ( & mut self ) {
333
+ unsafe { bindings:: pci_free_irq_vectors ( self . ptr ) } ;
334
+ }
335
+
336
+ pub fn request_irq < T : irq:: Handler > (
337
+ & self ,
338
+ index : u32 ,
339
+ data : T :: Data ,
340
+ name_args : fmt:: Arguments < ' _ > ,
341
+ ) -> Result < irq:: Registration < T > > {
342
+ let ret = unsafe { bindings:: pci_irq_vector ( self . ptr , index) } ;
343
+ if ret < 0 {
344
+ return Err ( Error :: from_errno ( ret) ) ;
345
+ }
346
+ crate :: pr_info!( "Setting up IRQ: {}\n " , ret) ;
347
+
348
+ irq:: Registration :: try_new ( ret as _ , data, irq:: flags:: SHARED , name_args)
223
349
}
224
350
}
225
351
0 commit comments