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 standard_device = transport.pci_device().as_standard_device().unwrap(); 37 standard_device 38 .irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI) 39 .ok_or(PciError::PciIrqError(PciIrqError::IrqNotInited))?; 40 // 中断相关信息 41 let msg = PciIrqMsg { 42 irq_common_message: IrqCommonMsg::init_from( 43 0, 44 "Virtio_IRQ".to_string(), 45 &DefaultVirtioIrqHandler, 46 dev_id, 47 ), 48 irq_specific_message: IrqSpecificMsg::msi_default(), 49 }; 50 standard_device.irq_install(msg)?; 51 standard_device.irq_enable(true)?; 52 } 53 return Ok(()); 54 } 55 } 56 57 impl core::fmt::Debug for VirtIOTransport { 58 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 59 match self { 60 VirtIOTransport::Pci(_) => write!(f, "VirtIOTransport::Pci"), 61 VirtIOTransport::Mmio(_) => write!(f, "VirtIOTransport::Mmio"), 62 } 63 } 64 } 65 66 impl Transport for VirtIOTransport { 67 #[inline(always)] 68 fn finish_init(&mut self) { 69 match self { 70 VirtIOTransport::Pci(transport) => transport.finish_init(), 71 VirtIOTransport::Mmio(transport) => transport.finish_init(), 72 } 73 } 74 75 #[inline(always)] 76 fn device_type(&self) -> virtio_drivers::transport::DeviceType { 77 match self { 78 VirtIOTransport::Pci(transport) => transport.device_type(), 79 VirtIOTransport::Mmio(transport) => transport.device_type(), 80 } 81 } 82 83 #[inline(always)] 84 fn read_device_features(&mut self) -> u64 { 85 match self { 86 VirtIOTransport::Pci(transport) => transport.read_device_features(), 87 VirtIOTransport::Mmio(transport) => transport.read_device_features(), 88 } 89 } 90 91 #[inline(always)] 92 fn write_driver_features(&mut self, driver_features: u64) { 93 match self { 94 VirtIOTransport::Pci(transport) => transport.write_driver_features(driver_features), 95 VirtIOTransport::Mmio(transport) => transport.write_driver_features(driver_features), 96 } 97 } 98 99 #[inline(always)] 100 fn max_queue_size(&mut self, queue: u16) -> u32 { 101 match self { 102 VirtIOTransport::Pci(transport) => transport.max_queue_size(queue), 103 VirtIOTransport::Mmio(transport) => transport.max_queue_size(queue), 104 } 105 } 106 107 #[inline(always)] 108 fn notify(&mut self, queue: u16) { 109 match self { 110 VirtIOTransport::Pci(transport) => transport.notify(queue), 111 VirtIOTransport::Mmio(transport) => transport.notify(queue), 112 } 113 } 114 115 #[inline(always)] 116 fn get_status(&self) -> virtio_drivers::transport::DeviceStatus { 117 match self { 118 VirtIOTransport::Pci(transport) => transport.get_status(), 119 VirtIOTransport::Mmio(transport) => transport.get_status(), 120 } 121 } 122 123 #[inline(always)] 124 fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) { 125 match self { 126 VirtIOTransport::Pci(transport) => transport.set_status(status), 127 VirtIOTransport::Mmio(transport) => transport.set_status(status), 128 } 129 } 130 131 #[inline(always)] 132 fn set_guest_page_size(&mut self, guest_page_size: u32) { 133 match self { 134 VirtIOTransport::Pci(transport) => transport.set_guest_page_size(guest_page_size), 135 VirtIOTransport::Mmio(transport) => transport.set_guest_page_size(guest_page_size), 136 } 137 } 138 139 #[inline(always)] 140 fn requires_legacy_layout(&self) -> bool { 141 match self { 142 VirtIOTransport::Pci(transport) => transport.requires_legacy_layout(), 143 VirtIOTransport::Mmio(transport) => transport.requires_legacy_layout(), 144 } 145 } 146 147 #[inline(always)] 148 fn queue_set( 149 &mut self, 150 queue: u16, 151 size: u32, 152 descriptors: virtio_drivers::PhysAddr, 153 driver_area: virtio_drivers::PhysAddr, 154 device_area: virtio_drivers::PhysAddr, 155 ) { 156 match self { 157 VirtIOTransport::Pci(transport) => { 158 transport.queue_set(queue, size, descriptors, driver_area, device_area) 159 } 160 VirtIOTransport::Mmio(transport) => { 161 transport.queue_set(queue, size, descriptors, driver_area, device_area) 162 } 163 } 164 } 165 166 #[inline(always)] 167 fn queue_unset(&mut self, queue: u16) { 168 match self { 169 VirtIOTransport::Pci(transport) => transport.queue_unset(queue), 170 VirtIOTransport::Mmio(transport) => transport.queue_unset(queue), 171 } 172 } 173 174 #[inline(always)] 175 fn queue_used(&mut self, queue: u16) -> bool { 176 match self { 177 VirtIOTransport::Pci(transport) => transport.queue_used(queue), 178 VirtIOTransport::Mmio(transport) => transport.queue_used(queue), 179 } 180 } 181 182 #[inline(always)] 183 fn ack_interrupt(&mut self) -> bool { 184 match self { 185 VirtIOTransport::Pci(transport) => transport.ack_interrupt(), 186 VirtIOTransport::Mmio(transport) => transport.ack_interrupt(), 187 } 188 } 189 190 #[inline(always)] 191 fn config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>> { 192 match self { 193 VirtIOTransport::Pci(transport) => transport.config_space(), 194 VirtIOTransport::Mmio(transport) => transport.config_space(), 195 } 196 } 197 } 198