axfs/
dev.rs

1use axdriver::prelude::*;
2
3const BLOCK_SIZE: usize = 512;
4
5/// A disk device with a cursor.
6pub struct Disk {
7    block_id: u64,
8    offset: usize,
9    dev: AxBlockDevice,
10}
11
12impl Disk {
13    /// Create a new disk.
14    pub fn new(dev: AxBlockDevice) -> Self {
15        assert_eq!(BLOCK_SIZE, dev.block_size());
16        Self {
17            block_id: 0,
18            offset: 0,
19            dev,
20        }
21    }
22
23    /// Get the size of the disk.
24    pub fn size(&self) -> u64 {
25        self.dev.num_blocks() * BLOCK_SIZE as u64
26    }
27
28    /// Get the position of the cursor.
29    pub fn position(&self) -> u64 {
30        self.block_id * BLOCK_SIZE as u64 + self.offset as u64
31    }
32
33    /// Set the position of the cursor.
34    pub fn set_position(&mut self, pos: u64) {
35        self.block_id = pos / BLOCK_SIZE as u64;
36        self.offset = pos as usize % BLOCK_SIZE;
37    }
38
39    /// Read within one block, returns the number of bytes read.
40    pub fn read_one(&mut self, buf: &mut [u8]) -> DevResult<usize> {
41        let read_size = if self.offset == 0 && buf.len() >= BLOCK_SIZE {
42            // whole block
43            let mut data = [0u8; BLOCK_SIZE];
44            self.dev.read_block(self.block_id, &mut data)?;
45            buf[0..BLOCK_SIZE].copy_from_slice(&data);
46            // self.dev
47            //     .read_block(self.block_id, &mut buf[0..BLOCK_SIZE])?;
48            self.block_id += 1;
49            BLOCK_SIZE
50        } else {
51            // partial block
52            let mut data = [0u8; BLOCK_SIZE];
53            let start = self.offset;
54            let count = buf.len().min(BLOCK_SIZE - self.offset);
55
56            self.dev.read_block(self.block_id, &mut data)?;
57            buf[..count].copy_from_slice(&data[start..start + count]);
58
59            self.offset += count;
60            if self.offset >= BLOCK_SIZE {
61                self.block_id += 1;
62                self.offset -= BLOCK_SIZE;
63            }
64            count
65        };
66        Ok(read_size)
67    }
68
69    /// Write within one block, returns the number of bytes written.
70    pub fn write_one(&mut self, buf: &[u8]) -> DevResult<usize> {
71        let write_size = if self.offset == 0 && buf.len() >= BLOCK_SIZE {
72            // whole block
73            // copy data to kernel address space
74            // Because underlying driver assumes a linear mapping between virtual address and
75            // physical address when converting them, which is only present in kernel address space.
76            let data = buf[0..BLOCK_SIZE].to_vec();
77            self.dev.write_block(self.block_id, &data)?;
78            self.block_id += 1;
79            BLOCK_SIZE
80        } else {
81            // partial block
82            let mut data = [0u8; BLOCK_SIZE];
83            let start = self.offset;
84            let count = buf.len().min(BLOCK_SIZE - self.offset);
85
86            self.dev.read_block(self.block_id, &mut data)?;
87            data[start..start + count].copy_from_slice(&buf[..count]);
88            self.dev.write_block(self.block_id, &data)?;
89
90            self.offset += count;
91            if self.offset >= BLOCK_SIZE {
92                self.block_id += 1;
93                self.offset -= BLOCK_SIZE;
94            }
95            count
96        };
97        Ok(write_size)
98    }
99
100    /// Read a single block starting from the specified offset.
101    #[allow(unused)]
102    pub fn read_offset(&mut self, offset: usize) -> [u8; BLOCK_SIZE] {
103        let block_id = offset / BLOCK_SIZE;
104        let mut block_data = [0u8; BLOCK_SIZE];
105        self.dev
106            .read_block(block_id as u64, &mut block_data)
107            .unwrap();
108        block_data
109    }
110
111    /// Write single block starting from the specified offset.
112    #[allow(unused)]
113    pub fn write_offset(&mut self, offset: usize, buf: &[u8]) -> DevResult<usize> {
114        assert!(
115            buf.len() == BLOCK_SIZE,
116            "Buffer length must be equal to BLOCK_SIZE"
117        );
118        assert!(offset % BLOCK_SIZE == 0);
119        let block_id = offset / BLOCK_SIZE;
120        self.dev.write_block(block_id as u64, buf).unwrap();
121        Ok(buf.len())
122    }
123}