1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
/* Copyright (c) [2023] [Syswonder Community]
* [Rukos] is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
use axdriver::prelude::*;
const BLOCK_SIZE: usize = 512;
/// A disk device with a cursor.
pub struct Disk {
block_id: u64,
offset: usize,
dev: AxBlockDevice,
}
impl Disk {
/// Create a new disk.
pub fn new(dev: AxBlockDevice) -> Self {
assert_eq!(BLOCK_SIZE, dev.block_size());
Self {
block_id: 0,
offset: 0,
dev,
}
}
/// Get the size of the disk.
pub fn size(&self) -> u64 {
self.dev.num_blocks() * BLOCK_SIZE as u64
}
/// Get the position of the cursor.
pub fn position(&self) -> u64 {
self.block_id * BLOCK_SIZE as u64 + self.offset as u64
}
/// Set the position of the cursor.
pub fn set_position(&mut self, pos: u64) {
self.block_id = pos / BLOCK_SIZE as u64;
self.offset = pos as usize % BLOCK_SIZE;
}
/// Read within one block, returns the number of bytes read.
pub fn read_one(&mut self, buf: &mut [u8]) -> DevResult<usize> {
let read_size = if self.offset == 0 && buf.len() >= BLOCK_SIZE {
// whole block
self.dev
.read_block(self.block_id, &mut buf[0..BLOCK_SIZE])?;
self.block_id += 1;
BLOCK_SIZE
} else {
// partial block
let mut data = [0u8; BLOCK_SIZE];
let start = self.offset;
let count = buf.len().min(BLOCK_SIZE - self.offset);
self.dev.read_block(self.block_id, &mut data)?;
buf[..count].copy_from_slice(&data[start..start + count]);
self.offset += count;
if self.offset >= BLOCK_SIZE {
self.block_id += 1;
self.offset -= BLOCK_SIZE;
}
count
};
Ok(read_size)
}
/// Write within one block, returns the number of bytes written.
pub fn write_one(&mut self, buf: &[u8]) -> DevResult<usize> {
let write_size = if self.offset == 0 && buf.len() >= BLOCK_SIZE {
// whole block
self.dev.write_block(self.block_id, &buf[0..BLOCK_SIZE])?;
self.block_id += 1;
BLOCK_SIZE
} else {
// partial block
let mut data = [0u8; BLOCK_SIZE];
let start = self.offset;
let count = buf.len().min(BLOCK_SIZE - self.offset);
self.dev.read_block(self.block_id, &mut data)?;
data[start..start + count].copy_from_slice(&buf[..count]);
self.dev.write_block(self.block_id, &data)?;
self.offset += count;
if self.offset >= BLOCK_SIZE {
self.block_id += 1;
self.offset -= BLOCK_SIZE;
}
count
};
Ok(write_size)
}
}