lib.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //! VirtIO guest drivers.
  2. //!
  3. //! These drivers can be used by bare-metal code (such as a bootloader or OS kernel) running in a VM
  4. //! to interact with VirtIO devices provided by the VMM (such as QEMU or crosvm).
  5. //!
  6. //! # Usage
  7. //!
  8. //! You must first implement the [`Hal`] trait, to allocate DMA regions and translate between
  9. //! physical addresses (as seen by devices) and virtual addresses (as seen by your program). You can
  10. //! then construct the appropriate transport for the VirtIO device, e.g. for an MMIO device (perhaps
  11. //! discovered from the device tree):
  12. //!
  13. //! ```
  14. //! use core::ptr::NonNull;
  15. //! use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader};
  16. //!
  17. //! # fn example(mmio_device_address: usize) {
  18. //! let header = NonNull::new(mmio_device_address as *mut VirtIOHeader).unwrap();
  19. //! let transport = unsafe { MmioTransport::new(header) }.unwrap();
  20. //! # }
  21. //! ```
  22. //!
  23. //! You can then check what kind of VirtIO device it is and construct the appropriate driver:
  24. //!
  25. //! ```
  26. //! # use virtio_drivers::Hal;
  27. //! use virtio_drivers::{
  28. //! device::console::VirtIOConsole,
  29. //! transport::{mmio::MmioTransport, DeviceType, Transport},
  30. //! };
  31. //!
  32. //! # fn example<HalImpl: Hal>(transport: MmioTransport) {
  33. //! if transport.device_type() == DeviceType::Console {
  34. //! let mut console = VirtIOConsole::<HalImpl, _>::new(transport).unwrap();
  35. //! // Send a byte to the console.
  36. //! console.send(b'H').unwrap();
  37. //! }
  38. //! # }
  39. //! ```
  40. #![cfg_attr(not(test), no_std)]
  41. #![deny(unused_must_use, missing_docs)]
  42. #![allow(clippy::identity_op)]
  43. #![allow(dead_code)]
  44. #[cfg(any(feature = "alloc", test))]
  45. extern crate alloc;
  46. pub mod device;
  47. mod hal;
  48. mod queue;
  49. pub mod transport;
  50. mod volatile;
  51. pub use self::hal::{Hal, PhysAddr, VirtAddr};
  52. /// The page size in bytes supported by the library (4 KiB).
  53. pub const PAGE_SIZE: usize = 0x1000;
  54. /// The type returned by driver methods.
  55. pub type Result<T = ()> = core::result::Result<T, Error>;
  56. /// The error type of VirtIO drivers.
  57. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  58. pub enum Error {
  59. /// There are not enough descriptors available in the virtqueue, try again later.
  60. QueueFull,
  61. /// The device is not ready.
  62. NotReady,
  63. /// The queue is already in use.
  64. AlreadyUsed,
  65. /// Invalid parameter.
  66. InvalidParam,
  67. /// Failed to alloc DMA memory.
  68. DmaError,
  69. /// I/O Error
  70. IoError,
  71. /// The config space advertised by the device is smaller than the driver expected.
  72. ConfigSpaceTooSmall,
  73. /// The device doesn't have any config space, but the driver expects some.
  74. ConfigSpaceMissing,
  75. }
  76. /// Align `size` up to a page.
  77. fn align_up(size: usize) -> usize {
  78. (size + PAGE_SIZE) & !(PAGE_SIZE - 1)
  79. }
  80. /// The number of pages required to store `size` bytes, rounded up to a whole number of pages.
  81. fn pages(size: usize) -> usize {
  82. (size + PAGE_SIZE - 1) / PAGE_SIZE
  83. }