@@ -10,7 +10,7 @@ use core::{mem, ptr};
1010
1111use pci_types:: capability:: PciCapability ;
1212use virtio_spec:: pci:: {
13- CommonCfg , CommonCfgVolatileFieldAccess , CommonCfgVolatileWideFieldAccess ,
13+ Cap , CapCfgType , CommonCfg , CommonCfgVolatileFieldAccess , CommonCfgVolatileWideFieldAccess ,
1414 IsrStatus as IsrStatusRaw ,
1515} ;
1616use virtio_spec:: { le32, DeviceStatus } ;
@@ -39,13 +39,13 @@ use crate::drivers::virtio::error::VirtioError;
3939pub struct Origin {
4040 cfg_ptr : u16 , // Register to be read to reach configuration structure of type cfg_type
4141 dev_id : u16 ,
42- cap_struct : PciCapRaw ,
42+ cap_struct : Cap ,
4343}
4444
4545/// Maps a given device specific pci configuration structure and
4646/// returns a static reference to it.
4747pub fn map_dev_cfg < T > ( cap : & PciCap ) -> Option < & ' static mut T > {
48- if cap. cfg_type != virtio_spec :: pci :: Cap :: DeviceCfg {
48+ if cap. cfg_type != CapCfgType :: Device {
4949 error ! ( "Capability of device config has wrong id. Mapping not possible..." ) ;
5050 return None ;
5151 } ;
@@ -84,10 +84,10 @@ pub fn map_dev_cfg<T>(cap: &PciCap) -> Option<&'static mut T> {
8484/// as it is not directly mapped into address space from PCI device
8585/// configuration space.
8686/// Therefore the struct only contains necessary information to map
87- /// corresponding config type (`pci::Cap`) into address space.
87+ /// corresponding config type into address space.
8888#[ derive( Clone ) ]
8989pub struct PciCap {
90- cfg_type : virtio_spec :: pci :: Cap ,
90+ cfg_type : CapCfgType ,
9191 bar : PciBar ,
9292 id : u8 ,
9393 offset : MemOff ,
@@ -172,50 +172,11 @@ impl PciCap {
172172 }
173173}
174174
175- /// Virtio's PCI capabilities structure.
176- /// See Virtio specification v.1.1 - 4.1.4
177- ///
178- /// WARN: endianness of this structure should be seen as little endian.
179- /// As this structure is not meant to be used outside of this module and for
180- /// ease of conversion from reading data into struct from PCI configuration
181- /// space, no conversion is made for struct fields.
182- #[ derive( Clone , Debug ) ]
183- #[ repr( C ) ]
184- struct PciCapRaw {
185- cap_vndr : u8 ,
186- cap_next : u8 ,
187- cap_len : u8 ,
188- cfg_type : u8 ,
189- bar_index : u8 ,
190- id : u8 ,
191- padding : [ u8 ; 2 ] ,
192- offset : u32 ,
193- length : u32 ,
194- }
195-
196- // This only shows compiler, that structs are identical
197- // with themselves.
198- impl Eq for PciCapRaw { }
199-
200- // In order to compare two PciCapRaw structs PartialEq is needed
201- impl PartialEq for PciCapRaw {
202- fn eq ( & self , other : & Self ) -> bool {
203- self . cap_vndr == other. cap_vndr
204- && self . cap_next == other. cap_next
205- && self . cap_len == other. cap_len
206- && self . cfg_type == other. cfg_type
207- && self . bar_index == other. bar_index
208- && self . id == other. id
209- && self . offset == other. offset
210- && self . length == other. length
211- }
212- }
213-
214175/// Universal Caplist Collections holds all universal capability structures for
215176/// a given Virtio PCI device.
216177///
217178/// As Virtio's PCI devices are allowed to present multiple capability
218- /// structures of the same config type (`pci::Cap`) , the structure
179+ /// structures of the same config type, the structure
219180/// provides a driver with all capabilities, sorted in descending priority,
220181/// allowing the driver to choose.
221182/// The structure contains a special dev_cfg_list field, a vector holding
@@ -597,7 +558,7 @@ impl NotifCfg {
597558 // Assumes the cap_len is a multiple of 8
598559 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment.
599560 let notify_off_multiplier_ptr =
600- cap. origin . cfg_ptr + u16:: try_from ( mem:: size_of :: < PciCapRaw > ( ) ) . unwrap ( ) ;
561+ cap. origin . cfg_ptr + u16:: try_from ( mem:: size_of :: < Cap > ( ) ) . unwrap ( ) ;
601562 let notify_off_multiplier = cap. device . read_register ( notify_off_multiplier_ptr) ;
602563
603564 // define base memory address from which the actual Queue Notify address can be derived via
@@ -785,23 +746,24 @@ impl ShMemCfg {
785746
786747 // Assumes the cap_len is a multiple of 8
787748 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment.
788- let offset_hi_ptr =
789- cap. origin . cfg_ptr + u16:: try_from ( mem:: size_of :: < PciCapRaw > ( ) ) . unwrap ( ) ;
749+ let offset_hi_ptr = cap. origin . cfg_ptr + u16:: try_from ( mem:: size_of :: < Cap > ( ) ) . unwrap ( ) ;
790750 let offset_hi = cap. device . read_register ( offset_hi_ptr) ;
791751
792752 // Create 64 bit offset from high and low 32 bit values
793- let offset =
794- MemOff :: from ( ( u64:: from ( offset_hi) << 32 ) ^ u64:: from ( cap. origin . cap_struct . offset ) ) ;
753+ let offset = MemOff :: from (
754+ ( u64:: from ( offset_hi) << 32 ) ^ u64:: from ( cap. origin . cap_struct . offset . to_ne ( ) ) ,
755+ ) ;
795756
796757 // Assumes the cap_len is a multiple of 8
797758 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment.
798759 let length_hi_ptr = cap. origin . cfg_ptr
799- + u16:: try_from ( mem:: size_of :: < PciCapRaw > ( ) + mem:: size_of :: < u32 > ( ) ) . unwrap ( ) ;
760+ + u16:: try_from ( mem:: size_of :: < Cap > ( ) + mem:: size_of :: < u32 > ( ) ) . unwrap ( ) ;
800761 let length_hi = cap. device . read_register ( length_hi_ptr) ;
801762
802763 // Create 64 bit length from high and low 32 bit values
803- let length =
804- MemLen :: from ( ( u64:: from ( length_hi) << 32 ) ^ u64:: from ( cap. origin . cap_struct . length ) ) ;
764+ let length = MemLen :: from (
765+ ( u64:: from ( length_hi) << 32 ) ^ u64:: from ( cap. origin . cap_struct . length . to_ne ( ) ) ,
766+ ) ;
805767
806768 let virt_addr_raw = cap. bar . mem_addr + offset;
807769 let raw_ptr = ptr:: with_exposed_provenance_mut :: < u8 > ( virt_addr_raw. into ( ) ) ;
@@ -885,36 +847,6 @@ impl PciBar {
885847 }
886848}
887849
888- /// Reads a raw capability struct [PciCapRaw] out of a PCI device's configuration space.
889- fn read_cap_raw ( device : & PciDevice < PciConfigRegion > , register : u16 ) -> PciCapRaw {
890- let mut quadruple_word: [ u8 ; 16 ] = [ 0 ; 16 ] ;
891-
892- debug ! ( "Converting read word from PCI device config space into native endian bytes." ) ;
893-
894- // Write words sequentially into array
895- for i in 0 ..4 {
896- // Read word need to be converted to little endian bytes as PCI is little endian.
897- // Interpretation of multi byte values needs to be swapped for big endian machines
898- let word: [ u8 ; 4 ] = device. read_register ( register + 4 * i) . to_le_bytes ( ) ;
899- let i = 4 * i as usize ;
900- quadruple_word[ i..i + 4 ] . copy_from_slice ( & word) ;
901- }
902-
903- PciCapRaw {
904- cap_vndr : quadruple_word[ 0 ] ,
905- cap_next : quadruple_word[ 1 ] ,
906- cap_len : quadruple_word[ 2 ] ,
907- cfg_type : quadruple_word[ 3 ] ,
908- bar_index : quadruple_word[ 4 ] ,
909- id : quadruple_word[ 5 ] ,
910- // Unwrapping is okay here, as transformed array slice is always 2 * u8 long and initialized
911- padding : quadruple_word[ 6 ..8 ] . try_into ( ) . unwrap ( ) ,
912- // Unwrapping is okay here, as transformed array slice is always 4 * u8 long and initialized
913- offset : u32:: from_le_bytes ( quadruple_word[ 8 ..12 ] . try_into ( ) . unwrap ( ) ) ,
914- length : u32:: from_le_bytes ( quadruple_word[ 12 ..16 ] . try_into ( ) . unwrap ( ) ) ,
915- }
916- }
917-
918850/// Reads all PCI capabilities, starting at the capabilities list pointer from the
919851/// PCI device.
920852///
@@ -933,17 +865,17 @@ fn read_caps(
933865 PciCapability :: Vendor ( capability) => Some ( capability) ,
934866 _ => None ,
935867 } )
936- . map ( |capability| ( capability. offset , read_cap_raw ( device, capability. offset ) ) )
937- . filter ( |( _ptr, capability) | capability. cfg_type != virtio_spec:: pci:: Cap :: PciCfg . into ( ) )
868+ . map ( |addr| {
869+ let cap = Cap :: read ( addr. clone ( ) , device. access ( ) ) . unwrap ( ) ;
870+ ( addr. offset , cap)
871+ } )
872+ . filter ( |( _ptr, capability) | capability. cfg_type != CapCfgType :: Pci . into ( ) )
938873 . map ( |( ptr, capability) | PciCap {
939- cfg_type : virtio_spec:: pci:: Cap :: from ( capability. cfg_type ) ,
940- bar : * bars
941- . iter ( )
942- . find ( |bar| bar. index == capability. bar_index )
943- . unwrap ( ) ,
874+ cfg_type : CapCfgType :: from ( capability. cfg_type ) ,
875+ bar : * bars. iter ( ) . find ( |bar| bar. index == capability. bar ) . unwrap ( ) ,
944876 id : capability. id ,
945- offset : MemOff :: from ( capability. offset ) ,
946- length : MemLen :: from ( capability. length ) ,
877+ offset : MemOff :: from ( capability. offset . to_ne ( ) ) ,
878+ length : MemLen :: from ( capability. length . to_ne ( ) ) ,
947879 device : * device,
948880 origin : Origin {
949881 cfg_ptr : ptr,
@@ -1003,36 +935,36 @@ pub(crate) fn map_caps(device: &PciDevice<PciConfigRegion>) -> Result<UniCapsCol
1003935 // Map Caps in virtual memory
1004936 for pci_cap in cap_list {
1005937 match pci_cap. cfg_type {
1006- virtio_spec :: pci :: Cap :: CommonCfg => match pci_cap. map_common_cfg ( ) {
938+ CapCfgType :: Common => match pci_cap. map_common_cfg ( ) {
1007939 Some ( cap) => caps. add_cfg_common ( ComCfg :: new ( cap, pci_cap. id ) ) ,
1008940 None => error ! (
1009941 "Common config capability with id {}, of device {:x}, could not be mapped!" ,
1010942 pci_cap. id, device_id
1011943 ) ,
1012944 } ,
1013- virtio_spec :: pci :: Cap :: NotifyCfg => match NotifCfg :: new ( & pci_cap) {
945+ CapCfgType :: Notify => match NotifCfg :: new ( & pci_cap) {
1014946 Some ( notif) => caps. add_cfg_notif ( notif) ,
1015947 None => error ! (
1016948 "Notification config capability with id {}, of device {:x} could not be used!" ,
1017949 pci_cap. id, device_id
1018950 ) ,
1019951 } ,
1020- virtio_spec :: pci :: Cap :: IsrCfg => match pci_cap. map_isr_status ( ) {
952+ CapCfgType :: Isr => match pci_cap. map_isr_status ( ) {
1021953 Some ( isr_stat) => caps. add_cfg_isr ( IsrStatus :: new ( isr_stat, pci_cap. id ) ) ,
1022954 None => error ! (
1023955 "ISR status config capability with id {}, of device {:x} could not be used!" ,
1024956 pci_cap. id, device_id
1025957 ) ,
1026958 } ,
1027- virtio_spec :: pci :: Cap :: PciCfg => caps. add_cfg_alt ( PciCfgAlt :: new ( & pci_cap) ) ,
1028- virtio_spec :: pci :: Cap :: SharedMemoryCfg => match ShMemCfg :: new ( & pci_cap) {
959+ CapCfgType :: Pci => caps. add_cfg_alt ( PciCfgAlt :: new ( & pci_cap) ) ,
960+ CapCfgType :: SharedMemory => match ShMemCfg :: new ( & pci_cap) {
1029961 Some ( sh_mem) => caps. add_cfg_sh_mem ( sh_mem) ,
1030962 None => error ! (
1031963 "Shared Memory config capability with id {}, of device {:x} could not be used!" ,
1032964 pci_cap. id, device_id
1033965 ) ,
1034966 } ,
1035- virtio_spec :: pci :: Cap :: DeviceCfg => caps. add_cfg_dev ( pci_cap) ,
967+ CapCfgType :: Device => caps. add_cfg_dev ( pci_cap) ,
1036968
1037969 // PCI's configuration space is allowed to hold other structures, which are not virtio specific and are therefore ignored
1038970 // in the following
0 commit comments