88
99use crate :: {
1010 bindings, device, driver,
11- error:: { from_result, to_result, Result } ,
11+ error:: { from_result, to_result, Error , Result } ,
12+ io_mem:: Resource ,
13+ irq,
1214 str:: CStr ,
1315 types:: ForeignOwnable ,
1416 ThisModule ,
1517} ;
18+ use core:: fmt;
1619
1720/// An adapter for the registration of PCI drivers.
1821pub struct Adapter < T : Driver > ( T ) ;
@@ -177,6 +180,7 @@ macro_rules! define_pci_id_table {
177180 } ;
178181 } ;
179182}
183+ pub use define_pci_id_table;
180184
181185/// A PCI driver
182186pub trait Driver {
@@ -187,7 +191,9 @@ pub trait Driver {
187191 ///
188192 /// Require that `Data` implements `ForeignOwnable`. We guarantee to
189193 /// 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 = ( ) ;
191197
192198 /// The type holding information about each device id supported by the driver.
193199 type IdInfo : ' static = ( ) ;
@@ -215,11 +221,131 @@ pub trait Driver {
215221/// The field `ptr` is non-null and valid for the lifetime of the object.
216222pub struct Device {
217223 ptr : * mut bindings:: pci_dev ,
224+ res_taken : u64 ,
218225}
219226
220227impl 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)
223349 }
224350}
225351
0 commit comments