1 use alloc::{string::ToString, sync::Arc}; 2 3 use virtio_drivers::transport::Transport; 4 5 use crate::{ 6 driver::{ 7 base::device::DeviceId, 8 pci::{ 9 pci::{PciDeviceStructure, PciError}, 10 pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqError, PciIrqMsg, IRQ}, 11 }, 12 }, 13 exception::IrqNumber, 14 }; 15 16 use super::{ 17 irq::DefaultVirtioIrqHandler, transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport, 18 }; 19 20 pub enum VirtIOTransport { 21 Pci(PciTransport), 22 Mmio(VirtIOMmioTransport), 23 } 24 25 impl VirtIOTransport { 26 pub fn irq(&self) -> IrqNumber { 27 match self { 28 VirtIOTransport::Pci(transport) => transport.irq(), 29 VirtIOTransport::Mmio(transport) => IrqNumber::new(transport.irq().data()), 30 } 31 } 32 33 /// 设置中断 34 pub fn setup_irq(&self, dev_id: Arc<DeviceId>) -> Result<(), PciError> { 35 if let VirtIOTransport::Pci(transport) = self { 36 let mut pci_device_guard = transport.pci_device(); 37 let standard_device = pci_device_guard.as_standard_device_mut().unwrap(); 38 standard_device 39 .irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI) 40 .ok_or(PciError::PciIrqError(PciIrqError::IrqNotInited))?; 41 // 中断相关信息 42 let msg = PciIrqMsg { 43 irq_common_message: IrqCommonMsg::init_from( 44 0, 45 "Virtio_IRQ".to_string(), 46 &DefaultVirtioIrqHandler, 47 dev_id, 48 ), 49 irq_specific_message: IrqSpecificMsg::msi_default(), 50 }; 51 standard_device.irq_install(msg)?; 52 standard_device.irq_enable(true)?; 53 } 54 return Ok(()); 55 } 56 } 57 58 impl core::fmt::Debug for VirtIOTransport { 59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 60 match self { 61 VirtIOTransport::Pci(_) => write!(f, "VirtIOTransport::Pci"), 62 VirtIOTransport::Mmio(_) => write!(f, "VirtIOTransport::Mmio"), 63 } 64 } 65 } 66 67 impl Transport for VirtIOTransport { 68 #[inline(always)] 69 fn finish_init(&mut self) { 70 match self { 71 VirtIOTransport::Pci(transport) => transport.finish_init(), 72 VirtIOTransport::Mmio(transport) => transport.finish_init(), 73 } 74 } 75 76 #[inline(always)] 77 fn device_type(&self) -> virtio_drivers::transport::DeviceType { 78 match self { 79 VirtIOTransport::Pci(transport) => transport.device_type(), 80 VirtIOTransport::Mmio(transport) => transport.device_type(), 81 } 82 } 83 84 #[inline(always)] 85 fn read_device_features(&mut self) -> u64 { 86 match self { 87 VirtIOTransport::Pci(transport) => transport.read_device_features(), 88 VirtIOTransport::Mmio(transport) => transport.read_device_features(), 89 } 90 } 91 92 #[inline(always)] 93 fn write_driver_features(&mut self, driver_features: u64) { 94 match self { 95 VirtIOTransport::Pci(transport) => transport.write_driver_features(driver_features), 96 VirtIOTransport::Mmio(transport) => transport.write_driver_features(driver_features), 97 } 98 } 99 100 #[inline(always)] 101 fn max_queue_size(&mut self, queue: u16) -> u32 { 102 match self { 103 VirtIOTransport::Pci(transport) => transport.max_queue_size(queue), 104 VirtIOTransport::Mmio(transport) => transport.max_queue_size(queue), 105 } 106 } 107 108 #[inline(always)] 109 fn notify(&mut self, queue: u16) { 110 match self { 111 VirtIOTransport::Pci(transport) => transport.notify(queue), 112 VirtIOTransport::Mmio(transport) => transport.notify(queue), 113 } 114 } 115 116 #[inline(always)] 117 fn get_status(&self) -> virtio_drivers::transport::DeviceStatus { 118 match self { 119 VirtIOTransport::Pci(transport) => transport.get_status(), 120 VirtIOTransport::Mmio(transport) => transport.get_status(), 121 } 122 } 123 124 #[inline(always)] 125 fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) { 126 match self { 127 VirtIOTransport::Pci(transport) => transport.set_status(status), 128 VirtIOTransport::Mmio(transport) => transport.set_status(status), 129 } 130 } 131 132 #[inline(always)] 133 fn set_guest_page_size(&mut self, guest_page_size: u32) { 134 match self { 135 VirtIOTransport::Pci(transport) => transport.set_guest_page_size(guest_page_size), 136 VirtIOTransport::Mmio(transport) => transport.set_guest_page_size(guest_page_size), 137 } 138 } 139 140 #[inline(always)] 141 fn requires_legacy_layout(&self) -> bool { 142 match self { 143 VirtIOTransport::Pci(transport) => transport.requires_legacy_layout(), 144 VirtIOTransport::Mmio(transport) => transport.requires_legacy_layout(), 145 } 146 } 147 148 #[inline(always)] 149 fn queue_set( 150 &mut self, 151 queue: u16, 152 size: u32, 153 descriptors: virtio_drivers::PhysAddr, 154 driver_area: virtio_drivers::PhysAddr, 155 device_area: virtio_drivers::PhysAddr, 156 ) { 157 match self { 158 VirtIOTransport::Pci(transport) => { 159 transport.queue_set(queue, size, descriptors, driver_area, device_area) 160 } 161 VirtIOTransport::Mmio(transport) => { 162 transport.queue_set(queue, size, descriptors, driver_area, device_area) 163 } 164 } 165 } 166 167 #[inline(always)] 168 fn queue_unset(&mut self, queue: u16) { 169 match self { 170 VirtIOTransport::Pci(transport) => transport.queue_unset(queue), 171 VirtIOTransport::Mmio(transport) => transport.queue_unset(queue), 172 } 173 } 174 175 #[inline(always)] 176 fn queue_used(&mut self, queue: u16) -> bool { 177 match self { 178 VirtIOTransport::Pci(transport) => transport.queue_used(queue), 179 VirtIOTransport::Mmio(transport) => transport.queue_used(queue), 180 } 181 } 182 183 #[inline(always)] 184 fn ack_interrupt(&mut self) -> bool { 185 match self { 186 VirtIOTransport::Pci(transport) => transport.ack_interrupt(), 187 VirtIOTransport::Mmio(transport) => transport.ack_interrupt(), 188 } 189 } 190 191 #[inline(always)] 192 fn config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>> { 193 match self { 194 VirtIOTransport::Pci(transport) => transport.config_space(), 195 VirtIOTransport::Mmio(transport) => transport.config_space(), 196 } 197 } 198 } 199