main.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #![no_std]
  2. #![no_main]
  3. #![deny(warnings)]
  4. extern crate alloc;
  5. extern crate opensbi_rt;
  6. use alloc::vec;
  7. use core::ptr::NonNull;
  8. use fdt::{node::FdtNode, standard_nodes::Compatible, Fdt};
  9. use log::{info, warn, LevelFilter};
  10. use virtio_drivers::*;
  11. use virtio_impl::HalImpl;
  12. mod virtio_impl;
  13. #[no_mangle]
  14. extern "C" fn main(_hartid: usize, device_tree_paddr: usize) {
  15. log::set_max_level(LevelFilter::Info);
  16. init_dt(device_tree_paddr);
  17. info!("test end");
  18. }
  19. fn init_dt(dtb: usize) {
  20. info!("device tree @ {:#x}", dtb);
  21. // Safe because the pointer is a valid pointer to unaliased memory.
  22. let fdt = unsafe { Fdt::from_ptr(dtb as *const u8).unwrap() };
  23. walk_dt(fdt);
  24. }
  25. fn walk_dt(fdt: Fdt) {
  26. for node in fdt.all_nodes() {
  27. if let Some(compatible) = node.compatible() {
  28. if compatible.all().any(|s| s == "virtio,mmio") {
  29. virtio_probe(node);
  30. }
  31. }
  32. }
  33. }
  34. fn virtio_probe(node: FdtNode) {
  35. if let Some(reg) = node.reg().and_then(|mut reg| reg.next()) {
  36. let paddr = reg.starting_address as usize;
  37. let size = reg.size.unwrap();
  38. let vaddr = paddr;
  39. info!("walk dt addr={:#x}, size={:#x}", paddr, size);
  40. info!(
  41. "Device tree node {}: {:?}",
  42. node.name,
  43. node.compatible().map(Compatible::first),
  44. );
  45. let header = NonNull::new(vaddr as *mut VirtIOHeader).unwrap();
  46. match unsafe { MmioTransport::new(header) } {
  47. Err(e) => warn!("Error creating VirtIO MMIO transport: {}", e),
  48. Ok(transport) => {
  49. info!(
  50. "Detected virtio MMIO device with vendor id {:#X}, device type {:?}, version {:?}",
  51. transport.vendor_id(),
  52. transport.device_type(),
  53. transport.version(),
  54. );
  55. virtio_device(transport);
  56. }
  57. }
  58. }
  59. }
  60. fn virtio_device(transport: impl Transport) {
  61. match transport.device_type() {
  62. DeviceType::Block => virtio_blk(transport),
  63. DeviceType::GPU => virtio_gpu(transport),
  64. DeviceType::Input => virtio_input(transport),
  65. DeviceType::Network => virtio_net(transport),
  66. t => warn!("Unrecognized virtio device: {:?}", t),
  67. }
  68. }
  69. fn virtio_blk<T: Transport>(transport: T) {
  70. let mut blk = VirtIOBlk::<HalImpl, T>::new(transport).expect("failed to create blk driver");
  71. let mut input = vec![0xffu8; 512];
  72. let mut output = vec![0; 512];
  73. for i in 0..32 {
  74. for x in input.iter_mut() {
  75. *x = i as u8;
  76. }
  77. blk.write_block(i, &input).expect("failed to write");
  78. blk.read_block(i, &mut output).expect("failed to read");
  79. assert_eq!(input, output);
  80. }
  81. info!("virtio-blk test finished");
  82. }
  83. fn virtio_gpu<T: Transport>(transport: T) {
  84. let mut gpu = VirtIOGpu::<HalImpl, T>::new(transport).expect("failed to create gpu driver");
  85. let (width, height) = gpu.resolution().expect("failed to get resolution");
  86. let width = width as usize;
  87. let height = height as usize;
  88. info!("GPU resolution is {}x{}", width, height);
  89. let fb = gpu.setup_framebuffer().expect("failed to get fb");
  90. for y in 0..height {
  91. for x in 0..width {
  92. let idx = (y * width + x) * 4;
  93. fb[idx] = x as u8;
  94. fb[idx + 1] = y as u8;
  95. fb[idx + 2] = (x + y) as u8;
  96. }
  97. }
  98. gpu.flush().expect("failed to flush");
  99. info!("virtio-gpu test finished");
  100. }
  101. fn virtio_input<T: Transport>(transport: T) {
  102. //let mut event_buf = [0u64; 32];
  103. let mut _input =
  104. VirtIOInput::<HalImpl, T>::new(transport).expect("failed to create input driver");
  105. // loop {
  106. // input.ack_interrupt().expect("failed to ack");
  107. // info!("mouse: {:?}", input.mouse_xy());
  108. // }
  109. // TODO: handle external interrupt
  110. }
  111. fn virtio_net<T: Transport>(transport: T) {
  112. let mut net = VirtIONet::<HalImpl, T>::new(transport).expect("failed to create net driver");
  113. let mut buf = [0u8; 0x100];
  114. let len = net.recv(&mut buf).expect("failed to recv");
  115. info!("recv: {:?}", &buf[..len]);
  116. net.send(&buf[..len]).expect("failed to send");
  117. info!("virtio-net test finished");
  118. }