Crates.io | nvme-rs |
lib.rs | nvme-rs |
version | 0.5.4 |
created_at | 2025-09-04 04:11:14.627981+00 |
updated_at | 2025-09-26 01:01:16.531847+00 |
description | Bare-metal NVMe driver which will never be yanked |
homepage | |
repository | https://github.com/H4n-uL/NVMe-Rust |
max_upload_size | |
id | 1823631 |
size | 173,919 |
A no-std compatible NVMe driver for embedded and operating system development.
You need create a allocator that implements the NVMeAllocator
trait.
pub struct NVMeAllocator;
impl Allocator for NVMeAllocator {
unsafe fn allocate(&self, size: usize) -> usize {
DmaManager::allocate(size)
}
unsafe fn deallocate(&self, addr: usize) {
DmaManager::deallocate(addr);
}
fn translate(&self, addr: usize) -> usize {
DmaManager::translate_addr(addr)
}
}
Here is a complete example of a full routine that initializes the NVMe controller, identifies namespaces, and performs read/write operations.
pub fn nvme_test() -> Result<(), Box<dyn core::error::Error>> {
// Init the NVMe controller
let controller = NVMeDevice::init(virtual_address, Allocator)?;
// Some useful data you may want to see
let _controller_data = controller.controller_data();
// Select the first namespace
let namespace = controller.get_ns(1)?;
// You can get the block size and count of the namespace
let _disk_size = namespace.total_size();
// Should not be larger than controller_data.max_transfer_size
const TEST_LENGTH: usize = 524288;
// Create a 4096 byte aligned read buffer
let layout = Layout::from_size_align(TEST_LENGTH, 4096)?;
let read_buffer_ptr = unsafe { ALLOCATOR.alloc(layout) };
let read_buffer = unsafe { core::slice::from_raw_parts_mut(read_buffer_ptr, TEST_LENGTH) };
// Read `TEST_LENGTH` bytes starting from LBA 34
namespace.read(34, &mut read_buffer)?;
// Create a 4096 byte aligned write buffer
let write_buffer_ptr = unsafe { ALLOCATOR.alloc(layout) };
let write_buffer = unsafe { core::slice::from_raw_parts_mut(write_buffer_ptr, TEST_LENGTH) };
// Fill the write buffer with data
for i in 0..TEST_LENGTH {
write_buffer[i] = (i % 256) as u8;
}
// Write the buffer to the disk starting from LBA 34
namespace.write(34, &write_buffer)?;
// Read back the data to verify correctness
namespace.read(34, &mut read_buffer)?;
// Verify the data byte-by-byte
for (i, (read, write)) in read_buffer.iter().zip(write_buffer.iter()).enumerate() {
if read != write {
eprintln!("Write test: Mismatch at index {i}: {read} != {write}");
break;
}
}
// Don't forget to free the buffer
unsafe {
ALLOCATOR.dealloc(read_buffer_ptr, layout);
ALLOCATOR.dealloc(write_buffer_ptr, layout);
}
Ok(())
}
Abandoned (c)
@ LICENCE file?I was using nvme
crate, and one day original maintainers yanked all versions and nuked repo
luckily I had a cloned version(this) which fixed a spec violation before yank.