use super::io_mem::read_once;
use crate::{
arch::mm::__memcpy_fallible,
io::io_mem::util::{copy_from_mmio_val, copy_to_mmio_val, for_aligned_chunks, memset_mmio_val},
mm::PodOnce,
};
pub(super) unsafe fn copy_from_mmio(mut dst_ptr: *mut u8, mut src_io_ptr: *const u8, count: usize) {
if count == 0 {
return;
}
let copied = for_aligned_chunks!(
src_io_ptr.addr(),
count,
8,
copy_from_mmio_val(&mut dst_ptr, &mut src_io_ptr)
);
debug_assert_eq!(copied, count);
}
pub(super) unsafe fn copy_to_mmio(mut src_ptr: *const u8, mut dst_io_ptr: *mut u8, count: usize) {
if count == 0 {
return;
}
let copied = for_aligned_chunks!(
dst_io_ptr.addr(),
count,
8,
copy_to_mmio_val(&mut src_ptr, &mut dst_io_ptr)
);
debug_assert_eq!(copied, count);
}
pub(super) unsafe fn copy_from_mmio_fallible(
mut dst_ptr: *mut u8,
mut src_io_ptr: *const u8,
count: usize,
) -> usize {
for_aligned_chunks!(
src_io_ptr.addr(),
count,
8,
copy_from_mmio_val_fallible(&mut dst_ptr, &mut src_io_ptr)
)
}
pub(super) unsafe fn copy_to_mmio_fallible(
mut src_ptr: *const u8,
mut dst_io_ptr: *mut u8,
mut count: usize,
) -> usize {
const BUF_SIZE: usize = 256;
let mut buf = [0u8; BUF_SIZE];
let mut copied_total = 0;
while count > 0 {
let chunk = core::cmp::min(count, BUF_SIZE);
let failed = unsafe { __memcpy_fallible(buf.as_mut_ptr(), src_ptr, chunk) };
let copied = chunk - failed;
if copied < chunk {
return copied_total;
}
unsafe { copy_to_mmio(buf.as_ptr(), dst_io_ptr, chunk) };
dst_io_ptr = dst_io_ptr.wrapping_add(chunk);
src_ptr = src_ptr.wrapping_add(chunk);
copied_total += chunk;
count -= chunk;
}
copied_total
}
pub(super) unsafe fn memset_mmio(mut dst_io_ptr: *mut u8, value: u8, count: usize) {
if count == 0 {
return;
}
let written = for_aligned_chunks!(
dst_io_ptr.addr(),
count,
8,
memset_mmio_val(&mut dst_io_ptr, value)
);
debug_assert_eq!(written, count);
}
unsafe fn copy_from_mmio_val_fallible<T: PodOnce>(
dst_ptr: &mut *mut u8,
src_io_ptr: &mut *const u8,
) -> usize {
let value = unsafe { read_once::<T>((*src_io_ptr).cast::<T>()) };
let size = size_of::<T>();
let failed =
unsafe { __memcpy_fallible(*dst_ptr, core::ptr::addr_of!(value).cast::<u8>(), size) };
let copied = size - failed;
*dst_ptr = (*dst_ptr).wrapping_add(copied);
*src_io_ptr = (*src_io_ptr).wrapping_add(copied);
copied
}