xref: /DragonOS/kernel/src/driver/virtio/transport.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
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