@@ -4,8 +4,9 @@ use crate::asm::{in_dw, out_dw};
4
4
const PCI_CONFIG_ADDR : u16 = 0xCF8 ;
5
5
const PCI_CONFIG_DATA : u16 = 0xCFC ;
6
6
7
- /// PCI configuration space header.
7
+ /// Represents a PCI configuration space header.
8
8
pub struct PciConfig {
9
+ base_addr : u32 ,
9
10
vendor_id : u16 ,
10
11
device_id : u16 ,
11
12
command : u16 ,
@@ -19,56 +20,97 @@ pub struct PciConfig {
19
20
bar : [ u32 ; 6 ] ,
20
21
}
21
22
22
- /// Read a PCI vendor identifier.
23
- pub unsafe fn read_vendor_id ( base_addr : u32 ) -> u16 {
24
- let mut result: u16 = 0x0 ;
25
- for i in ( 0 ..=1 ) . rev ( ) {
26
- out_dw ( PCI_CONFIG_ADDR , base_addr | i) ;
27
- let data = in_dw ( PCI_CONFIG_DATA ) ;
28
- result |= ( data as u16 ) << ( i * 8 ) ;
23
+ impl PciConfig {
24
+ /// Read a new PciConfig struct from a memory mapped I/O address.
25
+ pub fn new ( base_addr : u32 ) -> Result < PciConfig , ( ) > {
26
+ unsafe {
27
+ let vendor_id = Self :: read_vendor_id ( base_addr) ;
28
+ let device_id = Self :: read_device_id ( base_addr) ;
29
+ let bar_0 = Self :: read_bar ( base_addr, 0 ) ;
30
+
31
+ Ok ( PciConfig {
32
+ base_addr : base_addr,
33
+ vendor_id : vendor_id,
34
+ device_id : device_id,
35
+ command : 0 ,
36
+ status : 0 ,
37
+ revision_id : 0 ,
38
+ class_code : [ 0u8 ; 3 ] ,
39
+ cache_line_size : 0 ,
40
+ lat_timer : 0 ,
41
+ header_type : 0 ,
42
+ bist : 0 ,
43
+ bar : [ bar_0, 0 , 0 , 0 , 0 , 0 ] ,
44
+ } )
45
+ }
29
46
}
30
- result
31
- }
32
47
33
- /// Read a PCI device identifier.
34
- pub unsafe fn read_device_id ( base_addr : u32 ) -> u16 {
35
- let mut result: u16 = 0x0 ;
36
- let mut j = 1 ;
37
- for i in ( 2 ..=3 ) . rev ( ) {
38
- out_dw ( PCI_CONFIG_ADDR , base_addr | i) ;
39
- let data = in_dw ( PCI_CONFIG_DATA ) ;
40
- result |= ( data as u16 ) << ( j * 8 ) ;
41
- j -= 1 ;
48
+ /// Return the vendor id associated with the device.
49
+ pub fn vendor_id ( & self ) -> u16 {
50
+ self . vendor_id
42
51
}
43
- result
44
- }
45
52
46
- /// Read the `n`th BAR register.
47
- pub unsafe fn read_bar ( device : u32 , _n : u8 ) -> u32 {
48
- let mut result: u32 = 0x0 ;
49
- let mut j = 3 ;
50
- for i in ( 16 ..=19 ) . rev ( ) {
51
- out_dw ( PCI_CONFIG_ADDR , ( 0x80000000 | device << 11 ) | i) ;
52
- let data = in_dw ( PCI_CONFIG_DATA ) ;
53
- result |= data << ( j * 8 ) ;
54
- j -= 1 ;
53
+ /// Return the device id associated with the device.
54
+ pub fn device_id ( & self ) -> u16 {
55
+ self . device_id
56
+ }
57
+
58
+ /// Return the value of the ith base address register.
59
+ pub fn bar ( & self , i : u8 ) -> u32 {
60
+ self . bar [ i as usize ]
55
61
}
56
- result
57
- }
58
62
59
- /// Setup the device as a bus master.
60
- pub unsafe fn set_bus_master ( device : u32 ) {
61
- let mut command: u32 = 0x0 ;
62
- let mut j = 1 ;
63
- for i in ( 4 ..=5 ) . rev ( ) {
64
- out_dw ( PCI_CONFIG_ADDR , ( 0x80000000 | device << 11 ) | i) ;
65
- let data = in_dw ( PCI_CONFIG_DATA ) ;
66
- command |= data << ( j * 8 ) ;
67
- j -= 1 ;
63
+ /// Set the device as a bus master.
64
+ pub unsafe fn set_bus_master ( & self ) {
65
+ let mut command: u32 = 0x0 ;
66
+ let mut j = 1 ;
67
+ for i in ( 4 ..=5 ) . rev ( ) {
68
+ out_dw ( PCI_CONFIG_ADDR , self . base_addr | i) ;
69
+ let data = in_dw ( PCI_CONFIG_DATA ) ;
70
+ command |= data << ( j * 8 ) ;
71
+ j -= 1 ;
72
+ }
73
+
74
+ // Set the bus master flag and write back the command register.
75
+ command |= 1 << 2 ;
76
+ out_dw ( PCI_CONFIG_ADDR , self . base_addr | 4 ) ;
77
+ out_dw ( PCI_CONFIG_DATA , command) ;
78
+ }
79
+
80
+ /// Read a PCI vendor identifier.
81
+ unsafe fn read_vendor_id ( base_addr : u32 ) -> u16 {
82
+ let mut result: u16 = 0x0 ;
83
+ for i in ( 0 ..=1 ) . rev ( ) {
84
+ out_dw ( PCI_CONFIG_ADDR , base_addr | i) ;
85
+ let data = in_dw ( PCI_CONFIG_DATA ) ;
86
+ result |= ( data as u16 ) << ( i * 8 ) ;
87
+ }
88
+ result
68
89
}
69
90
70
- // Set the bus master flag and write back the command register.
71
- command |= 1 << 2 ;
72
- out_dw ( PCI_CONFIG_ADDR , ( 0x80000000 | device << 11 ) | 4 ) ;
73
- out_dw ( PCI_CONFIG_DATA , command) ;
91
+ /// Read a PCI device identifier.
92
+ unsafe fn read_device_id ( base_addr : u32 ) -> u16 {
93
+ let mut result: u16 = 0x0 ;
94
+ let mut j = 1 ;
95
+ for i in ( 2 ..=3 ) . rev ( ) {
96
+ out_dw ( PCI_CONFIG_ADDR , base_addr | i) ;
97
+ let data = in_dw ( PCI_CONFIG_DATA ) ;
98
+ result |= ( data as u16 ) << ( j * 8 ) ;
99
+ j -= 1 ;
100
+ }
101
+ result
102
+ }
103
+
104
+ /// Read the nth BAR register.
105
+ unsafe fn read_bar ( base_addr : u32 , _n : u32 ) -> u32 {
106
+ let mut result: u32 = 0x0 ;
107
+ let mut j = 3 ;
108
+ for i in ( 16 ..=19 ) . rev ( ) {
109
+ out_dw ( PCI_CONFIG_ADDR , base_addr | i) ;
110
+ let data = in_dw ( PCI_CONFIG_DATA ) ;
111
+ result |= data << ( j * 8 ) ;
112
+ j -= 1 ;
113
+ }
114
+ result
115
+ }
74
116
}
0 commit comments