good_os_framework/drivers/
xhci.rs

1use core::num::NonZeroUsize;
2
3use x86_64::{
4    structures::paging::{Page, PageTableFlags, PhysFrame},
5    PhysAddr,
6};
7use xhci::accessor::Mapper;
8use xhci::Registers;
9
10use crate::memory::{convert_physical_to_virtual, FRAME_ALLOCATOR, KERNEL_PAGE_TABLE};
11
12#[derive(Clone)]
13pub struct XHCIMapper;
14
15impl Mapper for XHCIMapper {
16    unsafe fn map(&mut self, phys_start: usize, bytes: usize) -> core::num::NonZeroUsize {
17        let physical_address = PhysAddr::new(phys_start as u64);
18        let virtual_address = convert_physical_to_virtual(physical_address);
19
20        let pages = (bytes + 4095) / 4096;
21
22        for page_i in 0..pages {
23            use x86_64::structures::paging::Mapper;
24            if let Ok(tlb) = KERNEL_PAGE_TABLE.lock().map_to(
25                Page::containing_address(virtual_address + page_i as u64 * 4096),
26                PhysFrame::containing_address(physical_address + page_i as u64 * 4096),
27                PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
28                &mut *FRAME_ALLOCATOR.lock(),
29            ) {
30                tlb.flush();
31            }
32        }
33
34        NonZeroUsize::new(virtual_address.as_u64() as usize).unwrap()
35    }
36
37    fn unmap(&mut self, _virt_start: usize, _bytes: usize) {}
38}
39
40/// Returns the XHCI registers.
41pub fn get_xhci(mmio_base: usize) -> Registers<XHCIMapper> {
42    unsafe { Registers::new(mmio_base, XHCIMapper) }
43}