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