use ax_driver_base::{BaseDriverOps, DevError, DevResult, DeviceType};
use sg200x_bsp::sdmmc::Sdmmc;
use crate::BlockDriverOps;
const BLOCK_SIZE: usize = 512;
pub struct CvsdDriver(Sdmmc);
unsafe impl Send for CvsdDriver {}
unsafe impl Sync for CvsdDriver {}
impl CvsdDriver {
pub fn new(sdmmc: usize, syscon: usize) -> DevResult<Self> {
let sdmmc = unsafe { Sdmmc::new(sdmmc, syscon) };
sdmmc.init().map_err(|_| DevError::Io)?;
sdmmc.clk_en(true);
Ok(Self(sdmmc))
}
fn checked_u32_lba(block_id: u64, offset: usize) -> DevResult<u32> {
let lba = block_id
.checked_add(u64::try_from(offset).map_err(|_| DevError::InvalidParam)?)
.ok_or(DevError::InvalidParam)?;
u32::try_from(lba).map_err(|_| DevError::InvalidParam)
}
}
impl BaseDriverOps for CvsdDriver {
fn device_type(&self) -> DeviceType {
DeviceType::Block
}
fn device_name(&self) -> &str {
"cvsd"
}
}
impl BlockDriverOps for CvsdDriver {
fn num_blocks(&self) -> u64 {
self.0.card_capacity_blocks()
}
fn block_size(&self) -> usize {
BLOCK_SIZE
}
fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult {
let (blocks, remainder) = buf.as_chunks_mut::<{ BLOCK_SIZE }>();
if !remainder.is_empty() {
return Err(DevError::InvalidParam);
}
for (i, block) in blocks.iter_mut().enumerate() {
self.0
.read_block(Self::checked_u32_lba(block_id, i)?, block)
.map_err(|_| DevError::Io)?;
}
Ok(())
}
fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult {
let (blocks, remainder) = buf.as_chunks::<{ BLOCK_SIZE }>();
if !remainder.is_empty() {
return Err(DevError::InvalidParam);
}
for (i, block) in blocks.iter().enumerate() {
self.0
.write_block(Self::checked_u32_lba(block_id, i)?, block)
.map_err(|_| DevError::Io)?;
}
Ok(())
}
fn flush(&mut self) -> DevResult {
Ok(())
}
}