morpheus_network/asm/drivers/
virtio.rsuse crate::types::repr_c::{RxResult, VirtqueueState};
#[cfg(target_arch = "x86_64")]
extern "win64" {
fn asm_virtio_verify_magic(mmio_base: u64) -> u32;
fn asm_virtio_get_version(mmio_base: u64) -> u32;
fn asm_virtio_get_device_id(mmio_base: u64) -> u32;
fn asm_virtio_reset(mmio_base: u64) -> u32;
fn asm_virtio_set_status(mmio_base: u64, status: u8);
fn asm_virtio_get_status(mmio_base: u64) -> u8;
fn asm_virtio_read_features(mmio_base: u64) -> u64;
fn asm_virtio_write_features(mmio_base: u64, features: u64);
fn asm_virtio_read_mac(mmio_base: u64, mac_out: *mut [u8; 6]) -> u32;
}
#[cfg(target_arch = "x86_64")]
extern "win64" {
fn asm_vq_select(mmio_base: u64, queue_idx: u16);
fn asm_vq_get_max_size(mmio_base: u64) -> u16;
fn asm_vq_set_size(mmio_base: u64, size: u16);
fn asm_vq_set_desc(mmio_base: u64, addr: u64);
fn asm_vq_set_driver(mmio_base: u64, addr: u64);
fn asm_vq_set_device(mmio_base: u64, addr: u64);
fn asm_vq_enable(mmio_base: u64);
fn asm_vq_disable(mmio_base: u64);
fn asm_vq_is_ready(mmio_base: u64) -> u32;
fn asm_vq_setup(
mmio_base: u64,
queue_idx: u16,
size: u16,
desc_addr: u64,
driver_addr: u64,
device_addr: u64,
);
fn asm_vq_init_desc(desc_table: u64, idx: u16, addr: u64, len: u32, flags: u16, next: u16);
fn asm_vq_init_desc_chain(
desc_table: u64,
start_idx: u16,
addrs: *const u64,
lens: *const u32,
count: u16,
write_flags: u16,
);
}
#[cfg(target_arch = "x86_64")]
extern "win64" {
fn asm_vq_submit_tx(vq: *mut VirtqueueState, buffer_idx: u16, buffer_len: u16) -> u32;
fn asm_vq_poll_tx_complete(vq: *mut VirtqueueState) -> u32;
fn asm_vq_tx_avail_slots(vq: *mut VirtqueueState) -> u16;
fn asm_vq_submit_rx(vq: *mut VirtqueueState, buffer_idx: u16, capacity: u16) -> u32;
fn asm_vq_poll_rx(vq: *mut VirtqueueState, result: *mut RxResult) -> u32;
fn asm_vq_rx_pending(vq: *mut VirtqueueState) -> u16;
}
#[cfg(target_arch = "x86_64")]
extern "win64" {
fn asm_vq_notify(vq: *mut VirtqueueState);
fn asm_vq_notify_direct(notify_addr: u64, queue_idx: u16);
fn asm_vq_should_notify(vq: *mut VirtqueueState) -> u32;
fn asm_vq_set_notify_addr(vq: *mut VirtqueueState, addr: u64);
}
pub mod device {
use super::*;
#[cfg(target_arch = "x86_64")]
pub fn verify_magic(mmio_base: u64) -> bool {
unsafe { asm_virtio_verify_magic(mmio_base) == 1 }
}
#[cfg(target_arch = "x86_64")]
pub fn get_version(mmio_base: u64) -> u32 {
unsafe { asm_virtio_get_version(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn get_device_id(mmio_base: u64) -> u32 {
unsafe { asm_virtio_get_device_id(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn reset(mmio_base: u64) -> bool {
unsafe { asm_virtio_reset(mmio_base) == 0 }
}
#[cfg(target_arch = "x86_64")]
pub fn set_status(mmio_base: u64, status: u8) {
unsafe { asm_virtio_set_status(mmio_base, status) }
}
#[cfg(target_arch = "x86_64")]
pub fn get_status(mmio_base: u64) -> u8 {
unsafe { asm_virtio_get_status(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn read_features(mmio_base: u64) -> u64 {
unsafe { asm_virtio_read_features(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn write_features(mmio_base: u64, features: u64) {
unsafe { asm_virtio_write_features(mmio_base, features) }
}
#[cfg(target_arch = "x86_64")]
pub fn read_mac(mmio_base: u64) -> Option<[u8; 6]> {
let mut mac = [0u8; 6];
if unsafe { asm_virtio_read_mac(mmio_base, &mut mac) } == 0 {
Some(mac)
} else {
None
}
}
#[cfg(not(target_arch = "x86_64"))]
pub fn verify_magic(_mmio_base: u64) -> bool {
false
}
#[cfg(not(target_arch = "x86_64"))]
pub fn get_version(_mmio_base: u64) -> u32 {
0
}
#[cfg(not(target_arch = "x86_64"))]
pub fn get_device_id(_mmio_base: u64) -> u32 {
0
}
#[cfg(not(target_arch = "x86_64"))]
pub fn reset(_mmio_base: u64) -> bool {
false
}
#[cfg(not(target_arch = "x86_64"))]
pub fn set_status(_mmio_base: u64, _status: u8) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn get_status(_mmio_base: u64) -> u8 {
0
}
#[cfg(not(target_arch = "x86_64"))]
pub fn read_features(_mmio_base: u64) -> u64 {
0
}
#[cfg(not(target_arch = "x86_64"))]
pub fn write_features(_mmio_base: u64, _features: u64) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn read_mac(_mmio_base: u64) -> Option<[u8; 6]> {
None
}
}
pub mod queue {
use super::*;
#[cfg(target_arch = "x86_64")]
pub fn select(mmio_base: u64, queue_idx: u16) {
unsafe { asm_vq_select(mmio_base, queue_idx) }
}
#[cfg(target_arch = "x86_64")]
pub fn get_max_size(mmio_base: u64) -> u16 {
unsafe { asm_vq_get_max_size(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn get_size(mmio_base: u64) -> u16 {
unsafe { asm_vq_get_max_size(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn set_size(mmio_base: u64, size: u16) {
unsafe { asm_vq_set_size(mmio_base, size) }
}
#[cfg(target_arch = "x86_64")]
pub fn set_desc_addr(mmio_base: u64, addr: u64) {
unsafe { asm_vq_set_desc(mmio_base, addr) }
}
#[cfg(target_arch = "x86_64")]
pub fn set_driver_addr(mmio_base: u64, addr: u64) {
unsafe { asm_vq_set_driver(mmio_base, addr) }
}
#[cfg(target_arch = "x86_64")]
pub fn set_device_addr(mmio_base: u64, addr: u64) {
unsafe { asm_vq_set_device(mmio_base, addr) }
}
#[cfg(target_arch = "x86_64")]
pub fn enable(mmio_base: u64) {
unsafe { asm_vq_enable(mmio_base) }
}
#[cfg(target_arch = "x86_64")]
pub fn setup(
mmio_base: u64,
queue_idx: u16,
size: u16,
desc_addr: u64,
driver_addr: u64,
device_addr: u64,
) {
unsafe {
asm_vq_setup(
mmio_base,
queue_idx,
size,
desc_addr,
driver_addr,
device_addr,
)
}
}
#[cfg(target_arch = "x86_64")]
pub fn get_notify_offset(_mmio_base: u64) -> u64 {
0x50 }
#[cfg(not(target_arch = "x86_64"))]
pub fn select(_mmio_base: u64, _queue_idx: u16) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn get_max_size(_mmio_base: u64) -> u16 {
0
}
#[cfg(not(target_arch = "x86_64"))]
pub fn get_size(_mmio_base: u64) -> u16 {
0
}
#[cfg(not(target_arch = "x86_64"))]
pub fn set_size(_mmio_base: u64, _size: u16) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn set_desc_addr(_mmio_base: u64, _addr: u64) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn set_driver_addr(_mmio_base: u64, _addr: u64) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn set_device_addr(_mmio_base: u64, _addr: u64) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn enable(_mmio_base: u64) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn setup(
_mmio_base: u64,
_queue_idx: u16,
_size: u16,
_desc_addr: u64,
_driver_addr: u64,
_device_addr: u64,
) {
}
#[cfg(not(target_arch = "x86_64"))]
pub fn get_notify_offset(_mmio_base: u64) -> u64 {
0x50
}
}
pub mod tx {
use super::*;
#[cfg(target_arch = "x86_64")]
pub fn submit(vq: &mut VirtqueueState, buffer_idx: u16, len: u16) -> bool {
unsafe { asm_vq_submit_tx(vq, buffer_idx, len) == 0 }
}
#[cfg(target_arch = "x86_64")]
pub fn poll_complete(vq: &mut VirtqueueState) -> Option<u16> {
let result = unsafe { asm_vq_poll_tx_complete(vq) };
if result == 0xFFFFFFFF {
None
} else {
Some(result as u16)
}
}
#[cfg(target_arch = "x86_64")]
pub fn available_slots(vq: &mut VirtqueueState) -> u16 {
unsafe { asm_vq_tx_avail_slots(vq) }
}
#[cfg(not(target_arch = "x86_64"))]
pub fn submit(_vq: &mut VirtqueueState, _buffer_idx: u16, _len: u16) -> bool {
false
}
#[cfg(not(target_arch = "x86_64"))]
pub fn poll_complete(_vq: &mut VirtqueueState) -> Option<u16> {
None
}
#[cfg(not(target_arch = "x86_64"))]
pub fn available_slots(_vq: &mut VirtqueueState) -> u16 {
0
}
}
pub mod rx {
use super::*;
#[cfg(target_arch = "x86_64")]
pub fn submit(vq: &mut VirtqueueState, buffer_idx: u16, capacity: u16) -> bool {
unsafe { asm_vq_submit_rx(vq, buffer_idx, capacity) == 0 }
}
#[cfg(target_arch = "x86_64")]
pub fn poll(vq: &mut VirtqueueState) -> Option<RxResult> {
let mut result = RxResult::default();
if unsafe { asm_vq_poll_rx(vq, &mut result) } == 1 {
Some(result)
} else {
None
}
}
#[cfg(target_arch = "x86_64")]
pub fn pending_count(vq: &mut VirtqueueState) -> u16 {
unsafe { asm_vq_rx_pending(vq) }
}
#[cfg(not(target_arch = "x86_64"))]
pub fn submit(_vq: &mut VirtqueueState, _buffer_idx: u16, _capacity: u16) -> bool {
false
}
#[cfg(not(target_arch = "x86_64"))]
pub fn poll(_vq: &mut VirtqueueState) -> Option<RxResult> {
None
}
#[cfg(not(target_arch = "x86_64"))]
pub fn pending_count(_vq: &mut VirtqueueState) -> u16 {
0
}
}
pub mod notify {
use super::*;
#[cfg(target_arch = "x86_64")]
pub fn notify(vq: &mut VirtqueueState) {
if vq.notify_addr == 0 || vq.notify_addr < 0x1000 {
return; }
unsafe { asm_vq_notify(vq) }
}
#[cfg(target_arch = "x86_64")]
pub fn notify_direct(notify_addr: u64, queue_idx: u16) {
unsafe { asm_vq_notify_direct(notify_addr, queue_idx) }
}
#[cfg(target_arch = "x86_64")]
pub fn should_notify(vq: &mut VirtqueueState) -> bool {
unsafe { asm_vq_should_notify(vq) == 1 }
}
#[cfg(not(target_arch = "x86_64"))]
pub fn notify(_vq: &mut VirtqueueState) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn notify_direct(_notify_addr: u64, _queue_idx: u16) {}
#[cfg(not(target_arch = "x86_64"))]
pub fn should_notify(_vq: &mut VirtqueueState) -> bool {
false
}
}