Skip to main content

axdriver_block/
bcm2835sdhci.rs

1//! SD card driver for raspi4
2
3use axdriver_base::{BaseDriverOps, DevError, DevResult, DeviceType};
4use bcm2835_sdhci::{
5    Bcm2835SDhci::{BLOCK_SIZE, EmmcCtl},
6    SDHCIError,
7};
8
9use crate::BlockDriverOps;
10
11/// BCM2835 SDHCI driver (Raspberry Pi SD card).
12pub struct SDHCIDriver(EmmcCtl);
13
14impl SDHCIDriver {
15    /// Initialize the SDHCI driver, returns `Ok` if successful.
16    pub fn try_new() -> DevResult<SDHCIDriver> {
17        let mut ctrl = EmmcCtl::new();
18        if ctrl.init() == 0 {
19            log::info!("BCM2835 sdhci: successfully initialized");
20            Ok(SDHCIDriver(ctrl))
21        } else {
22            log::warn!("BCM2835 sdhci: init failed");
23            Err(DevError::Io)
24        }
25    }
26}
27
28fn deal_sdhci_err(err: SDHCIError) -> DevError {
29    match err {
30        SDHCIError::Io => DevError::Io,
31        SDHCIError::AlreadyExists => DevError::AlreadyExists,
32        SDHCIError::Again => DevError::Again,
33        SDHCIError::BadState => DevError::BadState,
34        SDHCIError::InvalidParam => DevError::InvalidParam,
35        SDHCIError::NoMemory => DevError::NoMemory,
36        SDHCIError::ResourceBusy => DevError::ResourceBusy,
37        SDHCIError::Unsupported => DevError::Unsupported,
38    }
39}
40
41impl BaseDriverOps for SDHCIDriver {
42    fn device_type(&self) -> DeviceType {
43        DeviceType::Block
44    }
45
46    fn device_name(&self) -> &str {
47        "bcm2835_sdhci"
48    }
49}
50
51impl BlockDriverOps for SDHCIDriver {
52    fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult {
53        if buf.len() < BLOCK_SIZE {
54            return Err(DevError::InvalidParam);
55        }
56        let (prefix, aligned_buf, suffix) = unsafe { buf.align_to_mut::<u32>() };
57        if !prefix.is_empty() || !suffix.is_empty() {
58            return Err(DevError::InvalidParam);
59        }
60        self.0
61            .read_block(block_id as u32, 1, aligned_buf)
62            .map_err(deal_sdhci_err)
63    }
64
65    fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult {
66        if buf.len() < BLOCK_SIZE {
67            return Err(DevError::Io);
68        }
69        let (prefix, aligned_buf, suffix) = unsafe { buf.align_to::<u32>() };
70        if !prefix.is_empty() || !suffix.is_empty() {
71            return Err(DevError::InvalidParam);
72        }
73        self.0
74            .write_block(block_id as u32, 1, aligned_buf)
75            .map_err(deal_sdhci_err)
76    }
77    fn flush(&mut self) -> DevResult {
78        Ok(())
79    }
80
81    #[inline]
82    fn num_blocks(&self) -> u64 {
83        self.0.get_block_num()
84    }
85
86    #[inline]
87    fn block_size(&self) -> usize {
88        self.0.get_block_size()
89    }
90}