console.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. use super::*;
  2. use crate::queue::VirtQueue;
  3. use bitflags::*;
  4. use core::sync::atomic::spin_loop_hint;
  5. use log::*;
  6. use volatile::{ReadOnly, WriteOnly};
  7. const QUEUE_RECEIVEQ_PORT_0: usize = 0;
  8. const QUEUE_TRANSMITQ_PORT_0: usize = 1;
  9. /// Virtio console. Only one single port is allowed since ``alloc'' is disabled.
  10. /// Emergency and cols/rows unimplemented.
  11. pub struct VirtIOConsole<'a> {
  12. header: &'static mut VirtIOHeader,
  13. receiveq: VirtQueue<'a>,
  14. transmitq: VirtQueue<'a>,
  15. queue_buf_dma: DMA,
  16. queue_buf_rx: &'a mut [u8],
  17. cursor: usize,
  18. pending_len: usize,
  19. }
  20. impl<'a> VirtIOConsole<'a> {
  21. /// Create a new VirtIO-Console driver.
  22. pub fn new(header: &'static mut VirtIOHeader) -> Result<Self> {
  23. header.begin_init(|features| {
  24. let features = Features::from_bits_truncate(features);
  25. info!("Device features {:?}", features);
  26. let supported_features = Features::empty();
  27. (features & supported_features).bits()
  28. });
  29. let config = unsafe { &mut *(header.config_space() as *mut Config) };
  30. info!("Config: {:?}", config);
  31. let receiveq = VirtQueue::new(header, QUEUE_RECEIVEQ_PORT_0, 2)?;
  32. let transmitq = VirtQueue::new(header, QUEUE_TRANSMITQ_PORT_0, 2)?;
  33. let queue_buf_dma = DMA::new(1)?;
  34. let queue_buf_rx = unsafe { &mut queue_buf_dma.as_buf()[0..] };
  35. header.finish_init();
  36. let mut console = VirtIOConsole {
  37. header,
  38. receiveq,
  39. transmitq,
  40. queue_buf_dma,
  41. queue_buf_rx,
  42. cursor: 0,
  43. pending_len: 0,
  44. };
  45. console.poll_retrieve()?;
  46. Ok(console)
  47. }
  48. fn poll_retrieve(&mut self) -> Result<()> {
  49. self.receiveq.add(&[], &[self.queue_buf_rx])?;
  50. Ok(())
  51. }
  52. /// Acknowledge interrupt.
  53. pub fn ack_interrupt(&mut self) -> Result<bool> {
  54. let ack = self.header.ack_interrupt();
  55. if !ack {
  56. return Ok(false);
  57. }
  58. let mut flag = false;
  59. while let Ok((_token, len)) = self.receiveq.pop_used() {
  60. assert_eq!(flag, false);
  61. flag = true;
  62. assert_ne!(len, 0);
  63. self.cursor = 0;
  64. self.pending_len = len as usize;
  65. }
  66. Ok(flag)
  67. }
  68. /// Try get char.
  69. pub fn recv(&mut self, pop: bool) -> Result<Option<u8>> {
  70. if self.cursor == self.pending_len {
  71. return Ok(None);
  72. }
  73. let ch = self.queue_buf_rx[self.cursor];
  74. if pop {
  75. self.cursor += 1;
  76. if self.cursor == self.pending_len {
  77. self.poll_retrieve()?;
  78. }
  79. }
  80. Ok(Some(ch))
  81. }
  82. /// Put a char onto the device.
  83. pub fn send(&mut self, chr: u8) -> Result<()> {
  84. let buf: [u8; 1] = [chr];
  85. self.transmitq.add(&[&buf], &[])?;
  86. self.header.notify(QUEUE_TRANSMITQ_PORT_0 as u32);
  87. while !self.transmitq.can_pop() {
  88. spin_loop_hint();
  89. }
  90. self.transmitq.pop_used()?;
  91. Ok(())
  92. }
  93. }
  94. #[repr(C)]
  95. #[derive(Debug)]
  96. struct Config {
  97. cols: ReadOnly<u16>,
  98. rows: ReadOnly<u16>,
  99. max_nr_ports: ReadOnly<u32>,
  100. emerg_wr: WriteOnly<u32>,
  101. }
  102. bitflags! {
  103. struct Features: u64 {
  104. const SIZE = 1 << 0;
  105. const MULTIPORT = 1 << 1;
  106. const EMERG_WRITE = 1 << 2;
  107. // device independent
  108. const NOTIFY_ON_EMPTY = 1 << 24; // legacy
  109. const ANY_LAYOUT = 1 << 27; // legacy
  110. const RING_INDIRECT_DESC = 1 << 28;
  111. const RING_EVENT_IDX = 1 << 29;
  112. const UNUSED = 1 << 30; // legacy
  113. const VERSION_1 = 1 << 32; // detect legacy
  114. // since virtio v1.1
  115. const ACCESS_PLATFORM = 1 << 33;
  116. const RING_PACKED = 1 << 34;
  117. const IN_ORDER = 1 << 35;
  118. const ORDER_PLATFORM = 1 << 36;
  119. const SR_IOV = 1 << 37;
  120. const NOTIFICATION_DATA = 1 << 38;
  121. }
  122. }