xref: /DragonOS/kernel/src/driver/virtio/transport_mmio.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1731bc2b3SLoGin use core::ptr::NonNull;
2731bc2b3SLoGin 
3731bc2b3SLoGin use alloc::sync::Arc;
4731bc2b3SLoGin use fdt::node::FdtNode;
5*2eab6dd7S曾俊 use log::info;
6731bc2b3SLoGin use system_error::SystemError;
7731bc2b3SLoGin use virtio_drivers::transport::{
8731bc2b3SLoGin     mmio::{MmioTransport, VirtIOHeader},
9731bc2b3SLoGin     Transport,
10731bc2b3SLoGin };
11731bc2b3SLoGin 
12731bc2b3SLoGin use crate::{
13731bc2b3SLoGin     arch::MMArch,
14731bc2b3SLoGin     driver::base::device::DeviceId,
15731bc2b3SLoGin     exception::HardwareIrqNumber,
16731bc2b3SLoGin     libs::align::page_align_up,
17731bc2b3SLoGin     mm::{
18731bc2b3SLoGin         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
19731bc2b3SLoGin         MemoryManagementArch, PhysAddr,
20731bc2b3SLoGin     },
21731bc2b3SLoGin };
22731bc2b3SLoGin 
23731bc2b3SLoGin pub struct VirtIOMmioTransport {
24731bc2b3SLoGin     mmio_transport: MmioTransport,
25731bc2b3SLoGin     _mmio_guard: MMIOSpaceGuard,
26731bc2b3SLoGin     irq: HardwareIrqNumber,
27731bc2b3SLoGin     device_id: Arc<DeviceId>,
28731bc2b3SLoGin }
29731bc2b3SLoGin 
30731bc2b3SLoGin impl VirtIOMmioTransport {
new(node: FdtNode) -> Result<Self, SystemError>31731bc2b3SLoGin     pub fn new(node: FdtNode) -> Result<Self, SystemError> {
32731bc2b3SLoGin         let reg = node
33731bc2b3SLoGin             .reg()
34731bc2b3SLoGin             .ok_or(SystemError::EINVAL)?
35731bc2b3SLoGin             .next()
36731bc2b3SLoGin             .ok_or(SystemError::EINVAL)?;
37731bc2b3SLoGin         let paddr = reg.starting_address as usize;
38731bc2b3SLoGin         let size = reg.size.unwrap_or(0);
39731bc2b3SLoGin         let page_offset = paddr % MMArch::PAGE_SIZE;
40731bc2b3SLoGin         let paddr = paddr - page_offset;
41731bc2b3SLoGin         let size = page_align_up(size + page_offset);
42731bc2b3SLoGin         let irq = node
43731bc2b3SLoGin             .interrupts()
44731bc2b3SLoGin             .ok_or(SystemError::EINVAL)?
45731bc2b3SLoGin             .next()
46731bc2b3SLoGin             .ok_or(SystemError::EINVAL)?;
47731bc2b3SLoGin 
48731bc2b3SLoGin         let device_id = DeviceId::new(None, Some(format!("virtio_mmio_{:#X}", paddr))).unwrap();
49731bc2b3SLoGin 
50731bc2b3SLoGin         let mmio_guard = mmio_pool().create_mmio(size)?;
51731bc2b3SLoGin         unsafe { mmio_guard.map_phys(PhysAddr::new(paddr), size) }?;
52731bc2b3SLoGin 
53731bc2b3SLoGin         let vaddr = mmio_guard.vaddr() + page_offset;
54731bc2b3SLoGin         let header = NonNull::new(vaddr.data() as *mut VirtIOHeader).unwrap();
55731bc2b3SLoGin 
56731bc2b3SLoGin         match unsafe { MmioTransport::new(header) } {
57731bc2b3SLoGin             Ok(mmio_transport) => {
58*2eab6dd7S曾俊                 info!( "Detected virtio MMIO device with vendor id {:#X}, device type {:?}, version {:?}, hw irq: {}",
59731bc2b3SLoGin                     mmio_transport.vendor_id(),
60731bc2b3SLoGin                     mmio_transport.device_type(),
61731bc2b3SLoGin                     mmio_transport.version(),
62731bc2b3SLoGin                     irq as u32
63731bc2b3SLoGin                 );
64731bc2b3SLoGin 
65731bc2b3SLoGin                 Ok(Self {
66731bc2b3SLoGin                     mmio_transport,
67731bc2b3SLoGin                     _mmio_guard: mmio_guard,
68731bc2b3SLoGin                     irq: HardwareIrqNumber::new(irq as u32),
69731bc2b3SLoGin                     device_id,
70731bc2b3SLoGin                 })
71731bc2b3SLoGin             }
72731bc2b3SLoGin             Err(_) => {
73*2eab6dd7S曾俊                 // warn!("MmioTransport::new failed: {:?}", e);
74731bc2b3SLoGin                 Err(SystemError::EINVAL)
75731bc2b3SLoGin             }
76731bc2b3SLoGin         }
77731bc2b3SLoGin     }
78731bc2b3SLoGin 
79731bc2b3SLoGin     #[allow(dead_code)]
80731bc2b3SLoGin     #[inline]
irq(&self) -> HardwareIrqNumber81731bc2b3SLoGin     pub fn irq(&self) -> HardwareIrqNumber {
82731bc2b3SLoGin         self.irq
83731bc2b3SLoGin     }
84731bc2b3SLoGin 
device_id(&self) -> Arc<DeviceId>85731bc2b3SLoGin     pub fn device_id(&self) -> Arc<DeviceId> {
86731bc2b3SLoGin         self.device_id.clone()
87731bc2b3SLoGin     }
88731bc2b3SLoGin }
89731bc2b3SLoGin 
90731bc2b3SLoGin impl Transport for VirtIOMmioTransport {
device_type(&self) -> virtio_drivers::transport::DeviceType91731bc2b3SLoGin     fn device_type(&self) -> virtio_drivers::transport::DeviceType {
92731bc2b3SLoGin         self.mmio_transport.device_type()
93731bc2b3SLoGin     }
94731bc2b3SLoGin 
read_device_features(&mut self) -> u6495731bc2b3SLoGin     fn read_device_features(&mut self) -> u64 {
96731bc2b3SLoGin         self.mmio_transport.read_device_features()
97731bc2b3SLoGin     }
98731bc2b3SLoGin 
write_driver_features(&mut self, driver_features: u64)99731bc2b3SLoGin     fn write_driver_features(&mut self, driver_features: u64) {
100731bc2b3SLoGin         self.mmio_transport.write_driver_features(driver_features)
101731bc2b3SLoGin     }
102731bc2b3SLoGin 
max_queue_size(&mut self, queue: u16) -> u32103731bc2b3SLoGin     fn max_queue_size(&mut self, queue: u16) -> u32 {
104731bc2b3SLoGin         self.mmio_transport.max_queue_size(queue)
105731bc2b3SLoGin     }
106731bc2b3SLoGin 
notify(&mut self, queue: u16)107731bc2b3SLoGin     fn notify(&mut self, queue: u16) {
108731bc2b3SLoGin         self.mmio_transport.notify(queue)
109731bc2b3SLoGin     }
110731bc2b3SLoGin 
get_status(&self) -> virtio_drivers::transport::DeviceStatus111731bc2b3SLoGin     fn get_status(&self) -> virtio_drivers::transport::DeviceStatus {
112731bc2b3SLoGin         self.mmio_transport.get_status()
113731bc2b3SLoGin     }
114731bc2b3SLoGin 
set_status(&mut self, status: virtio_drivers::transport::DeviceStatus)115731bc2b3SLoGin     fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) {
116731bc2b3SLoGin         self.mmio_transport.set_status(status)
117731bc2b3SLoGin     }
118731bc2b3SLoGin 
set_guest_page_size(&mut self, guest_page_size: u32)119731bc2b3SLoGin     fn set_guest_page_size(&mut self, guest_page_size: u32) {
120731bc2b3SLoGin         self.mmio_transport.set_guest_page_size(guest_page_size)
121731bc2b3SLoGin     }
122731bc2b3SLoGin 
requires_legacy_layout(&self) -> bool123731bc2b3SLoGin     fn requires_legacy_layout(&self) -> bool {
124731bc2b3SLoGin         self.mmio_transport.requires_legacy_layout()
125731bc2b3SLoGin     }
126731bc2b3SLoGin 
queue_set( &mut self, queue: u16, size: u32, descriptors: virtio_drivers::PhysAddr, driver_area: virtio_drivers::PhysAddr, device_area: virtio_drivers::PhysAddr, )127731bc2b3SLoGin     fn queue_set(
128731bc2b3SLoGin         &mut self,
129731bc2b3SLoGin         queue: u16,
130731bc2b3SLoGin         size: u32,
131731bc2b3SLoGin         descriptors: virtio_drivers::PhysAddr,
132731bc2b3SLoGin         driver_area: virtio_drivers::PhysAddr,
133731bc2b3SLoGin         device_area: virtio_drivers::PhysAddr,
134731bc2b3SLoGin     ) {
135731bc2b3SLoGin         self.mmio_transport
136731bc2b3SLoGin             .queue_set(queue, size, descriptors, driver_area, device_area)
137731bc2b3SLoGin     }
138731bc2b3SLoGin 
queue_unset(&mut self, queue: u16)139731bc2b3SLoGin     fn queue_unset(&mut self, queue: u16) {
140731bc2b3SLoGin         self.mmio_transport.queue_unset(queue)
141731bc2b3SLoGin     }
142731bc2b3SLoGin 
queue_used(&mut self, queue: u16) -> bool143731bc2b3SLoGin     fn queue_used(&mut self, queue: u16) -> bool {
144731bc2b3SLoGin         self.mmio_transport.queue_used(queue)
145731bc2b3SLoGin     }
146731bc2b3SLoGin 
ack_interrupt(&mut self) -> bool147731bc2b3SLoGin     fn ack_interrupt(&mut self) -> bool {
148731bc2b3SLoGin         self.mmio_transport.ack_interrupt()
149731bc2b3SLoGin     }
150731bc2b3SLoGin 
config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>>151731bc2b3SLoGin     fn config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>> {
152731bc2b3SLoGin         self.mmio_transport.config_space()
153731bc2b3SLoGin     }
154731bc2b3SLoGin 
finish_init(&mut self)155731bc2b3SLoGin     fn finish_init(&mut self) {
156731bc2b3SLoGin         self.mmio_transport.finish_init()
157731bc2b3SLoGin     }
158731bc2b3SLoGin }
159