kernel/drivers/virtio/device/
mod.rs1use core::result::Result;
5
6use alloc::{boxed::Box, vec};
7
8use crate::{device::{manager::DeviceManager, platform::{resource::PlatformDeviceResourceType, PlatformDeviceDriver, PlatformDeviceInfo}, Device}, driver_initcall, drivers::block::virtio_blk::VirtioBlockDevice};
9use super::queue::VirtQueue;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum Register {
19 MagicValue = 0x00,
20 Version = 0x04,
21 DeviceId = 0x08,
22 VendorId = 0x0c,
23 DeviceFeatures = 0x10,
24 DeviceFeaturesSel = 0x14,
25 DriverFeatures = 0x20,
26 DriverFeaturesSel = 0x24,
27 GuestPageSize = 0x28,
28 QueueSel = 0x30,
29 QueueNumMax = 0x34,
30 QueueNum = 0x38,
31 QueueAlign = 0x3c,
32 QueuePfn = 0x40,
33 QueueReady = 0x44,
34 QueueNotify = 0x50,
35 InterruptStatus = 0x60,
36 InterruptAck = 0x64,
37 Status = 0x70,
38 QueueDescLow = 0x80,
39 QueueDescHigh = 0x84,
40 DriverDescLow = 0x90,
41 DriverDescHigh = 0x94,
42 DeviceDescLow = 0xa0,
43 DeviceDescHigh = 0xa4,
44 DeviceConfig = 0x100,
45}
46
47impl Register {
48 pub fn offset(&self) -> usize {
49 *self as usize
50 }
51
52 pub fn from_offset(offset: usize) -> Self {
53 match offset {
54 0x00 => Register::MagicValue,
55 0x04 => Register::Version,
56 0x08 => Register::DeviceId,
57 0x0c => Register::VendorId,
58 0x10 => Register::DeviceFeatures,
59 0x14 => Register::DeviceFeaturesSel,
60 0x20 => Register::DriverFeatures,
61 0x24 => Register::DriverFeaturesSel,
62 0x28 => Register::GuestPageSize,
63 0x30 => Register::QueueSel,
64 0x34 => Register::QueueNumMax,
65 0x38 => Register::QueueNum,
66 0x3c => Register::QueueAlign,
67 0x40 => Register::QueuePfn,
68 0x44 => Register::QueueReady,
69 0x50 => Register::QueueNotify,
70 0x60 => Register::InterruptStatus,
71 0x64 => Register::InterruptAck,
72 0x70 => Register::Status,
73 0x80 => Register::QueueDescLow,
74 0x84 => Register::QueueDescHigh,
75 0x90 => Register::DriverDescLow,
76 0x94 => Register::DriverDescHigh,
77 0xa0 => Register::DeviceDescLow,
78 0xa4 => Register::DeviceDescHigh,
79 _ => panic!("Invalid register offset"),
80 }
81 }
82}
83
84#[derive(Debug, Clone, Copy)]
90pub enum DeviceStatus {
91 Reset = 0x00,
92 Acknowledge = 0x01,
93 Driver = 0x02,
94 DriverOK = 0x04,
95 FeaturesOK = 0x08,
96 DeviceNeedReset = 0x40,
97 Failed = 0x80,
98}
99
100impl DeviceStatus {
101 pub fn is_set(&self, status: u32) -> bool {
113 (status & *self as u32) != 0
114 }
115
116 pub fn set(&self, status: &mut u32) {
125 *status |= *self as u32;
126 }
127
128 pub fn clear(&self, status: &mut u32) {
137 *status &= !(*self as u32);
138 }
139
140 pub fn toggle(&self, status: &mut u32) {
149 *status ^= *self as u32;
150 }
151
152 pub fn from_u32(status: u32) -> Self {
165 match status {
166 0x00 => DeviceStatus::Reset,
167 0x01 => DeviceStatus::Acknowledge,
168 0x02 => DeviceStatus::Driver,
169 0x04 => DeviceStatus::DriverOK,
170 0x08 => DeviceStatus::FeaturesOK,
171 0x40 => DeviceStatus::DeviceNeedReset,
172 0x80 => DeviceStatus::Failed,
173 _ => panic!("Invalid device status"),
174 }
175 }
176
177 pub fn to_u32(&self) -> u32 {
186 *self as u32
187 }
188}
189
190pub trait VirtioDevice {
196 fn init(&mut self) -> Result<(), &'static str> {
206 if self.read32_register(Register::MagicValue) != 0x74726976 {
208 self.set_failed();
209 return Err("Invalid Magic Value");
210 }
211
212 let version = self.read32_register(Register::Version);
214 if version != 2 {
215 self.set_failed();
216 return Err("Invalid Version");
217 }
218
219 self.reset();
221
222 self.acknowledge();
224
225 self.driver();
227
228 if !self.negotiate_features() {
230 self.set_failed();
231 return Err("Feature negotiation failed");
232 }
233
234 for i in 0..self.get_virtqueue_count() {
236 if !self.setup_queue(i) {
237 self.set_failed();
238 return Err("Failed to set up virtqueue");
239 }
240 }
241
242 self.driver_ok();
244 Ok(())
245 }
246
247 fn reset(&mut self) {
249 self.write32_register(Register::Status, 0);
250 }
251
252 fn acknowledge(&mut self) {
254 let mut status = self.read32_register(Register::Status);
255 DeviceStatus::Acknowledge.set(&mut status);
256 self.write32_register(Register::Status, status);
257 }
258
259 fn driver(&mut self) {
261 let mut status = self.read32_register(Register::Status);
262 DeviceStatus::Driver.set(&mut status);
263 self.write32_register(Register::Status, status);
264 }
265
266 fn driver_ok(&mut self) {
268 let mut status = self.read32_register(Register::Status);
269 DeviceStatus::DriverOK.set(&mut status);
270 self.write32_register(Register::Status, status);
271 }
272
273 fn set_failed(&mut self) {
275 let mut status = self.read32_register(Register::Status);
276 DeviceStatus::Failed.set(&mut status);
277 self.write32_register(Register::Status, status);
278 }
279
280 fn negotiate_features(&mut self) -> bool {
289 let device_features = self.read32_register(Register::DeviceFeatures);
291 let driver_features = self.get_supported_features(device_features);
293 self.write32_register(Register::DriverFeatures, driver_features);
295
296 let mut status = self.read32_register(Register::Status);
298 DeviceStatus::FeaturesOK.set(&mut status);
299 self.write32_register(Register::Status, status);
300
301 let status = self.read32_register(Register::Status);
303 DeviceStatus::FeaturesOK.is_set(status)
304 }
305
306 fn get_supported_features(&self, device_features: u32) -> u32 {
319 device_features
322 }
323
324 fn setup_queue(&mut self, queue_idx: usize) -> bool {
337 if queue_idx >= self.get_virtqueue_count() {
338 return false;
339 }
340
341 self.write32_register(Register::QueueSel, queue_idx as u32);
343 let ready = self.read32_register(Register::QueueReady);
345 if ready != 0 {
346 return false; }
348
349 let queue_size = self.read32_register(Register::QueueNumMax);
351 if queue_size == 0 {
352 return false; }
354
355 self.write32_register(Register::QueueNum, queue_size);
357
358 let virtqueue = self.get_virtqueue(queue_idx);
359
360 let desc_addr = virtqueue.get_raw_ptr() as u64;
362 let desc_addr_low = (desc_addr & 0xffffffff) as u32;
363 let desc_addr_high = (desc_addr >> 32) as u32;
364 self.write32_register(Register::QueueDescLow, desc_addr_low);
365 self.write32_register(Register::QueueDescHigh, desc_addr_high);
366
367 let driver_addr = virtqueue.avail.flags as *const _ as u64;
369 let driver_addr_low = (driver_addr & 0xffffffff) as u32;
370 let driver_addr_high = (driver_addr >> 32) as u32;
371 self.write32_register(Register::DriverDescLow, driver_addr_low);
372 self.write32_register(Register::DriverDescHigh, driver_addr_high);
373
374 let device_addr = virtqueue.used.flags as *const _ as u64;
376 let device_addr_low = (device_addr & 0xffffffff) as u32;
377 let device_addr_high = (device_addr >> 32) as u32;
378 self.write32_register(Register::DeviceDescLow, device_addr_low);
379 self.write32_register(Register::DeviceDescHigh, device_addr_high);
380
381 let status = self.read32_register(Register::Status);
383 if DeviceStatus::Failed.is_set(status) {
384 return false; }
386
387 self.write32_register(Register::QueueReady, 1);
389
390 let status = self.read32_register(Register::Status);
392 if DeviceStatus::Failed.is_set(status) {
393 return false; }
395
396 true
397 }
398
399 fn read_config<T: Sized>(&self, offset: usize) -> T {
411 let addr = self.get_base_addr() + Register::DeviceConfig.offset() + offset;
412 unsafe { core::ptr::read_volatile(addr as *const T) }
413 }
414
415 fn write_config<T: Sized>(&self, offset: usize, value: T) {
424 let addr = self.get_base_addr() + Register::DeviceConfig.offset() + offset;
425 unsafe { core::ptr::write_volatile(addr as *mut T, value) }
426 }
427
428 fn get_device_info(&self) -> (u32, u32) {
434 let device_id = self.read32_register(Register::DeviceId);
435 let vendor_id = self.read32_register(Register::VendorId);
436 (device_id, vendor_id)
437 }
438
439 fn get_interrupt_status(&self) -> u32 {
445 self.read32_register(Register::InterruptStatus)
446 }
447
448 fn process_interrupts(&mut self) -> u32 {
456 let status = self.get_interrupt_status();
457 if status != 0 {
458 self.write32_register(Register::InterruptAck, status & 0x03);
459 }
460 status
461 }
462
463 fn memory_barrier(&self) {
465 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
466 }
467
468 fn notify(&mut self, virtqueue_idx: usize) {
481 if virtqueue_idx >= self.get_virtqueue_count() {
482 panic!("Invalid virtqueue index");
483 }
484 self.memory_barrier();
486 self.write32_register(Register::QueueNotify, virtqueue_idx as u32);
487 }
488
489 fn read32_register(&self, register: Register) -> u32 {
499 let addr = self.get_base_addr() + register.offset();
500 unsafe { core::ptr::read_volatile(addr as *const u32) }
501 }
502
503 fn write32_register(&self, register: Register, value: u32) {
510 let addr = self.get_base_addr() + register.offset();
511 unsafe { core::ptr::write_volatile(addr as *mut u32, value) }
512 }
513
514 fn read64_register(&self, register: Register) -> u64 {
524 let addr = self.get_base_addr() + register.offset();
525 unsafe { core::ptr::read_volatile(addr as *const u64) }
526 }
527
528 fn write64_register(&self, register: Register, value: u64) {
535 let addr = self.get_base_addr() + register.offset();
536 unsafe { core::ptr::write_volatile(addr as *mut u64, value) }
537 }
538
539 fn get_base_addr(&self) -> usize;
542 fn get_virtqueue_count(&self) -> usize;
543 fn get_virtqueue(&self, queue_idx: usize) -> &VirtQueue;
544}
545
546
547pub enum VirtioDeviceType {
553 Invalid = 0,
554 Net = 1,
555 Block = 2,
556 Console = 3,
557 Rng = 4,
558}
559
560impl VirtioDeviceType {
561 pub fn from_u32(device_type: u32) -> Self {
573 match device_type {
574 0 => VirtioDeviceType::Invalid,
575 1 => VirtioDeviceType::Net,
576 2 => VirtioDeviceType::Block,
577 3 => VirtioDeviceType::Console,
578 4 => VirtioDeviceType::Rng,
579 _ => panic!("Not supported device type"),
580 }
581 }
582}
583
584struct VirtioDeviceCommon {
590 base_addr: usize,
591}
592
593impl VirtioDeviceCommon {
594 pub fn new(base_addr: usize) -> Self {
604 Self { base_addr }
605 }
606}
607
608impl VirtioDevice for VirtioDeviceCommon {
609 fn init(&mut self) -> Result<(), &'static str> {
610 Ok(())
612 }
613
614 fn get_base_addr(&self) -> usize {
615 self.base_addr
616 }
617
618 fn get_virtqueue_count(&self) -> usize {
619 0
621 }
622
623 fn get_virtqueue(&self, _queue_idx: usize) -> &VirtQueue {
624 unimplemented!()
626 }
627}
628
629fn probe_fn(device: &PlatformDeviceInfo) -> Result<(), &'static str> {
630 let res = device.get_resources();
631 if res.is_empty() {
632 return Err("No resources found");
633 }
634
635 let mem_res = res.iter()
637 .find(|r| r.res_type == PlatformDeviceResourceType::MEM)
638 .ok_or("Memory resource not found")?;
639
640 let base_addr = mem_res.start as usize;
641
642 let virtio_device = VirtioDeviceCommon::new(base_addr);
644 let device_type = VirtioDeviceType::from_u32(virtio_device.get_device_info().0);
646
647 match device_type {
648 VirtioDeviceType::Block => {
649 let dev: Box<dyn Device> = Box::new(VirtioBlockDevice::new(base_addr));
650 DeviceManager::get_mut_manager().register_device(dev);
651 }
652 _ => {
653 return Err("Unsupported device type");
655 }
656 }
657
658 Ok(())
659}
660
661fn remove_fn(_device: &PlatformDeviceInfo) -> Result<(), &'static str> {
662 Ok(())
663}
664
665fn register_driver() {
666 let driver = PlatformDeviceDriver::new(
667 "virtio-mmio",
668 probe_fn,
669 remove_fn,
670 vec!["virtio,mmio"],
671 );
672 DeviceManager::get_mut_manager().register_driver(Box::new(driver))
674}
675
676driver_initcall!(register_driver);
677
678#[cfg(test)]
679mod tests;