main.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #![no_std]
  2. #![no_main]
  3. #![deny(warnings)]
  4. #[macro_use]
  5. extern crate log;
  6. extern crate alloc;
  7. extern crate opensbi_rt;
  8. use alloc::vec;
  9. use core::ptr::NonNull;
  10. use fdt::{node::FdtNode, standard_nodes::Compatible, Fdt};
  11. use log::LevelFilter;
  12. use virtio_drivers::{
  13. device::{blk::VirtIOBlk, gpu::VirtIOGpu, input::VirtIOInput, net::VirtIONet},
  14. transport::{
  15. mmio::{MmioTransport, VirtIOHeader},
  16. DeviceType, Transport,
  17. },
  18. };
  19. use virtio_impl::HalImpl;
  20. mod virtio_impl;
  21. #[cfg(feature = "tcp")]
  22. mod tcp;
  23. const NET_BUFFER_LEN: usize = 2048;
  24. const NET_QUEUE_SIZE: usize = 16;
  25. #[no_mangle]
  26. extern "C" fn main(_hartid: usize, device_tree_paddr: usize) {
  27. log::set_max_level(LevelFilter::Info);
  28. init_dt(device_tree_paddr);
  29. info!("test end");
  30. }
  31. fn init_dt(dtb: usize) {
  32. info!("device tree @ {:#x}", dtb);
  33. // Safe because the pointer is a valid pointer to unaliased memory.
  34. let fdt = unsafe { Fdt::from_ptr(dtb as *const u8).unwrap() };
  35. walk_dt(fdt);
  36. }
  37. fn walk_dt(fdt: Fdt) {
  38. for node in fdt.all_nodes() {
  39. if let Some(compatible) = node.compatible() {
  40. if compatible.all().any(|s| s == "virtio,mmio") {
  41. virtio_probe(node);
  42. }
  43. }
  44. }
  45. }
  46. fn virtio_probe(node: FdtNode) {
  47. if let Some(reg) = node.reg().and_then(|mut reg| reg.next()) {
  48. let paddr = reg.starting_address as usize;
  49. let size = reg.size.unwrap();
  50. let vaddr = paddr;
  51. info!("walk dt addr={:#x}, size={:#x}", paddr, size);
  52. info!(
  53. "Device tree node {}: {:?}",
  54. node.name,
  55. node.compatible().map(Compatible::first),
  56. );
  57. let header = NonNull::new(vaddr as *mut VirtIOHeader).unwrap();
  58. match unsafe { MmioTransport::new(header) } {
  59. Err(e) => warn!("Error creating VirtIO MMIO transport: {}", e),
  60. Ok(transport) => {
  61. info!(
  62. "Detected virtio MMIO device with vendor id {:#X}, device type {:?}, version {:?}",
  63. transport.vendor_id(),
  64. transport.device_type(),
  65. transport.version(),
  66. );
  67. virtio_device(transport);
  68. }
  69. }
  70. }
  71. }
  72. fn virtio_device(transport: impl Transport) {
  73. match transport.device_type() {
  74. DeviceType::Block => virtio_blk(transport),
  75. DeviceType::GPU => virtio_gpu(transport),
  76. DeviceType::Input => virtio_input(transport),
  77. DeviceType::Network => virtio_net(transport),
  78. t => warn!("Unrecognized virtio device: {:?}", t),
  79. }
  80. }
  81. fn virtio_blk<T: Transport>(transport: T) {
  82. let mut blk = VirtIOBlk::<HalImpl, T>::new(transport).expect("failed to create blk driver");
  83. let mut input = vec![0xffu8; 512];
  84. let mut output = vec![0; 512];
  85. for i in 0..32 {
  86. for x in input.iter_mut() {
  87. *x = i as u8;
  88. }
  89. blk.write_block(i, &input).expect("failed to write");
  90. blk.read_block(i, &mut output).expect("failed to read");
  91. assert_eq!(input, output);
  92. }
  93. info!("virtio-blk test finished");
  94. }
  95. fn virtio_gpu<T: Transport>(transport: T) {
  96. let mut gpu = VirtIOGpu::<HalImpl, T>::new(transport).expect("failed to create gpu driver");
  97. let (width, height) = gpu.resolution().expect("failed to get resolution");
  98. let width = width as usize;
  99. let height = height as usize;
  100. info!("GPU resolution is {}x{}", width, height);
  101. let fb = gpu.setup_framebuffer().expect("failed to get fb");
  102. for y in 0..height {
  103. for x in 0..width {
  104. let idx = (y * width + x) * 4;
  105. fb[idx] = x as u8;
  106. fb[idx + 1] = y as u8;
  107. fb[idx + 2] = (x + y) as u8;
  108. }
  109. }
  110. gpu.flush().expect("failed to flush");
  111. //delay some time
  112. info!("virtio-gpu show graphics....");
  113. for _ in 0..10000 {
  114. for _ in 0..100000 {
  115. unsafe {
  116. core::arch::asm!("nop");
  117. }
  118. }
  119. }
  120. info!("virtio-gpu test finished");
  121. }
  122. fn virtio_input<T: Transport>(transport: T) {
  123. //let mut event_buf = [0u64; 32];
  124. let mut _input =
  125. VirtIOInput::<HalImpl, T>::new(transport).expect("failed to create input driver");
  126. // loop {
  127. // input.ack_interrupt().expect("failed to ack");
  128. // info!("mouse: {:?}", input.mouse_xy());
  129. // }
  130. // TODO: handle external interrupt
  131. }
  132. fn virtio_net<T: Transport>(transport: T) {
  133. let net = VirtIONet::<HalImpl, T, NET_QUEUE_SIZE>::new(transport, NET_BUFFER_LEN)
  134. .expect("failed to create net driver");
  135. info!("MAC address: {:02x?}", net.mac_address());
  136. #[cfg(not(feature = "tcp"))]
  137. {
  138. let mut net = net;
  139. loop {
  140. match net.receive() {
  141. Ok(buf) => {
  142. info!("RECV {} bytes: {:02x?}", buf.packet_len(), buf.packet());
  143. let tx_buf = virtio_drivers::device::net::TxBuffer::from(buf.packet());
  144. net.send(tx_buf).expect("failed to send");
  145. net.recycle_rx_buffer(buf).unwrap();
  146. break;
  147. }
  148. Err(virtio_drivers::Error::NotReady) => continue,
  149. Err(err) => panic!("failed to recv: {:?}", err),
  150. }
  151. }
  152. info!("virtio-net test finished");
  153. }
  154. #[cfg(feature = "tcp")]
  155. tcp::test_echo_server(net);
  156. }