@@ -23,7 +23,7 @@ use crate::utils::bitmap::Bitmap;
2323use crate :: utils:: sync:: Mutex ;
2424
2525use crate :: acpi:: mcfg;
26- use crate :: mem:: paging:: OffsetPageTable ;
26+ use crate :: mem:: paging:: { OffsetPageTable , PhysAddr } ;
2727use crate :: utils:: VolatileCell ;
2828
2929use crate :: arch:: { apic, io} ;
@@ -116,16 +116,18 @@ impl<'a> Msix<'a> {
116116 . get_bar ( bar_index)
117117 . expect ( "msix: table bar not present" ) ;
118118
119+ map_bar ( & bar) ;
120+
119121 let bar_address = match bar {
120- Bar :: Memory64 { address, .. } => address,
121- Bar :: Memory32 { address, .. } => address as u64 ,
122+ Bar :: Memory64 { address, .. } => PhysAddr :: new ( address) ,
123+ Bar :: Memory32 { address, .. } => PhysAddr :: new ( address as u64 ) ,
122124 _ => unreachable ! ( ) ,
123125 } ;
124126
125127 // SAFETY: We have exclusive access to the BAR and the slice is in bounds.
126128 let messages = unsafe {
127129 core:: slice:: from_raw_parts_mut (
128- ( bar_address + bar_offset as u64 ) as * mut Message ,
130+ ( bar_address. as_hhdm_virt ( ) + bar_offset as u64 ) . as_mut_ptr :: < Message > ( ) ,
129131 table_length as usize ,
130132 )
131133 } ;
@@ -788,6 +790,45 @@ impl PciTable {
788790 }
789791}
790792
793+ pub fn map_bar ( bar : & Bar ) {
794+ use crate :: mem:: paging:: { Mapper , Page , PageTableFlags , PhysFrame , Size4KiB , UnmapError } ;
795+
796+ use crate :: mem:: AddressSpace ;
797+
798+ let mut address_space = AddressSpace :: this ( ) ;
799+ let mut offset_table = address_space. offset_page_table ( ) ;
800+
801+ let ( addr, size) = match bar {
802+ Bar :: Memory64 { address, size, .. } => ( PhysAddr :: new ( * address) , * size) ,
803+ _ => unreachable ! ( ) ,
804+ } ;
805+
806+ for frame in PhysFrame :: range (
807+ PhysFrame :: < Size4KiB > :: from_start_address ( addr) . unwrap ( ) ,
808+ PhysFrame :: containing_address ( addr + size) ,
809+ ) {
810+ let virt = frame. start_address ( ) . as_hhdm_virt ( ) ;
811+ let page = Page :: containing_address ( virt) ;
812+
813+ // Map will fail if the bar was partially mapped.
814+ match offset_table. unmap ( page) {
815+ Ok ( ( _, m) ) => m. ignore ( ) ,
816+ Err ( UnmapError :: PageNotMapped ) => { }
817+ Err ( e) => unreachable ! ( "{:?}" , e) ,
818+ }
819+
820+ unsafe {
821+ offset_table. map_to (
822+ page,
823+ frame,
824+ PageTableFlags :: PRESENT | PageTableFlags :: WRITABLE | PageTableFlags :: NO_EXECUTE ,
825+ )
826+ }
827+ . unwrap ( )
828+ . flush ( ) ;
829+ }
830+ }
831+
791832pub fn register_device_driver ( handle : Arc < dyn PciDeviceHandle > ) {
792833 PCI_TABLE . lock ( ) . inner . push ( PciDevice { handle } )
793834}
0 commit comments