1use alloc::format;
6
7use axdevice_base::DeviceError;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum VirtioError {
12 InvalidQueue,
14 QueueNotReady,
16 InvalidDescriptor,
18 InvalidAccessWidth,
20 DeviceNotReady,
22 InvalidDeviceIndex,
24 BackendError,
26 MemoryError,
28 InvalidConfig,
30 FeatureNegotiationFailed,
32 InvalidRequest,
34 NotSupported,
36 InvalidBufferSize,
38 InvalidSector,
40 InvalidRegister,
42 InvalidAddress,
44 RingMisaligned,
46 RingOverlap,
48 InvalidRingLayout,
51 QueueFaulted,
59 NotFound,
61 WouldBlock,
64 InvalidInput,
66}
67
68pub type VirtioResult<T> = Result<T, VirtioError>;
70
71pub fn map_virtio_error(error: VirtioError, operation: &'static str) -> DeviceError {
74 match error {
75 VirtioError::BackendError => DeviceError::Backend {
76 operation,
77 detail: format!("{error:?}"),
78 },
79 VirtioError::QueueFaulted => DeviceError::InvalidState {
80 operation,
81 detail: "queue faulted; guest reset required".into(),
82 },
83 VirtioError::QueueNotReady | VirtioError::DeviceNotReady => DeviceError::InvalidState {
84 operation,
85 detail: format!("{error:?}"),
86 },
87 VirtioError::WouldBlock => DeviceError::ResourceBusy {
88 operation,
89 resource: "VirtIO queue or reset transition".into(),
90 },
91 VirtioError::NotSupported => DeviceError::Unsupported {
92 operation,
93 detail: format!("{error:?}"),
94 },
95 VirtioError::MemoryError | VirtioError::InvalidAddress => DeviceError::InvalidData {
96 operation,
97 detail: format!("{error:?}"),
98 },
99 VirtioError::InvalidAccessWidth
100 | VirtioError::InvalidDeviceIndex
101 | VirtioError::InvalidRegister
102 | VirtioError::InvalidRequest
103 | VirtioError::FeatureNegotiationFailed
104 | VirtioError::InvalidInput => DeviceError::InvalidInput {
105 operation,
106 detail: format!("{error:?}"),
107 },
108 VirtioError::NotFound => DeviceError::NotFound,
109 VirtioError::InvalidQueue
110 | VirtioError::InvalidDescriptor
111 | VirtioError::InvalidConfig
112 | VirtioError::InvalidBufferSize
113 | VirtioError::InvalidSector
114 | VirtioError::RingMisaligned
115 | VirtioError::RingOverlap
116 | VirtioError::InvalidRingLayout => DeviceError::InvalidData {
117 operation,
118 detail: format!("{error:?}"),
119 },
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn preserves_runtime_error_categories() {
129 assert!(matches!(
130 map_virtio_error(VirtioError::BackendError, "test operation"),
131 DeviceError::Backend { .. }
132 ));
133 assert!(matches!(
134 map_virtio_error(VirtioError::QueueFaulted, "test operation"),
135 DeviceError::InvalidState { .. }
136 ));
137 assert!(matches!(
138 map_virtio_error(VirtioError::WouldBlock, "test operation"),
139 DeviceError::ResourceBusy { .. }
140 ));
141 assert!(matches!(
142 map_virtio_error(VirtioError::InvalidAddress, "test operation"),
143 DeviceError::InvalidData { .. }
144 ));
145 }
146}