inky_frame/fs/
block.rs

1// Permission is hereby granted, free of charge, to any person obtaining a copy
2// of this software and associated documentation files (the "Software"), to deal
3// in the Software without restriction, including without limitation the rights
4// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5// copies of the Software, and to permit persons to whom the Software is
6// furnished to do so, subject to the following conditions:
7//
8// The above copyright notice and this permission notice shall be included in
9// all copies or substantial portions of the Software.
10//
11// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17// SOFTWARE.
18//
19
20#![no_implicit_prelude]
21
22extern crate core;
23
24use core::default::Default;
25use core::ops::{Deref, DerefMut};
26use core::option::Option::{self, None, Some};
27use core::result::Result::{self, Ok};
28use core::{cmp, unreachable};
29
30use crate::fs::{BlockDevice, DeviceError, Storage};
31
32pub struct BlockBuffer {
33    buf:    [Block; 4],
34    status: u8,
35}
36pub struct BlockEntryIter {
37    buf:   BlockBuffer,
38    prev:  Option<u32>,
39    last:  u32,
40    count: u8,
41}
42#[repr(transparent)]
43pub struct BlockCache(Option<u32>);
44#[repr(transparent)]
45pub struct Block([u8; Block::SIZE]);
46
47impl Block {
48    pub const SIZE: usize = 0x200;
49
50    #[inline(always)]
51    pub const fn new() -> Block {
52        Block([0u8; Block::SIZE])
53    }
54
55    #[inline(always)]
56    pub fn clear(&mut self) {
57        self.0.fill(0)
58    }
59}
60impl BlockCache {
61    #[inline(always)]
62    pub fn new() -> BlockCache {
63        BlockCache(None)
64    }
65
66    #[inline(always)]
67    pub fn clear(&mut self) {
68        self.0.take();
69    }
70    #[inline]
71    pub fn read_single(&mut self, dev: &Storage<impl BlockDevice>, b: &mut Block, pos: u32) -> Result<(), DeviceError> {
72        match self.0.replace(pos) {
73            Some(v) if v != pos => dev.read_single(b, pos),
74            None => dev.read_single(b, pos),
75            _ => Ok(()),
76        }
77    }
78}
79impl BlockBuffer {
80    pub const COUNT: u8 = 0x4u8;
81    pub const SLOT_A: u8 = 0x0u8;
82    pub const SLOT_B: u8 = 0x1u8;
83    pub const SLOT_C: u8 = 0x2u8;
84    pub const SLOT_D: u8 = 0x3u8;
85
86    #[inline]
87    pub fn new() -> BlockBuffer {
88        BlockBuffer {
89            buf:    [Block::new(), Block::new(), Block::new(), Block::new()],
90            status: 0u8,
91        }
92    }
93
94    #[inline]
95    pub fn is_dirty(&self, slot: u8) -> bool {
96        match slot % BlockBuffer::COUNT {
97            BlockBuffer::SLOT_A if self.status & 0x80 != 0 => true,
98            BlockBuffer::SLOT_B if self.status & 0x40 != 0 => true,
99            BlockBuffer::SLOT_C if self.status & 0x20 != 0 => true,
100            BlockBuffer::SLOT_D if self.status & 0x10 != 0 => true,
101            _ => false,
102        }
103    }
104    #[inline]
105    pub fn is_loaded(&self, slot: u8) -> bool {
106        match slot % BlockBuffer::COUNT {
107            BlockBuffer::SLOT_A if self.status & 0x8 != 0 => true,
108            BlockBuffer::SLOT_B if self.status & 0x4 != 0 => true,
109            BlockBuffer::SLOT_C if self.status & 0x2 != 0 => true,
110            BlockBuffer::SLOT_D if self.status & 0x1 != 0 => true,
111            _ => false,
112        }
113    }
114    #[inline]
115    pub fn buffer(&mut self, slot: u8) -> &mut [u8] {
116        match slot % BlockBuffer::COUNT {
117            BlockBuffer::SLOT_A => {
118                self.status |= 0x80;
119                &mut self.buf[0]
120            },
121            BlockBuffer::SLOT_B => {
122                self.status |= 0x40;
123                &mut self.buf[1]
124            },
125            BlockBuffer::SLOT_C => {
126                self.status |= 0x20;
127                &mut self.buf[2]
128            },
129            BlockBuffer::SLOT_D => {
130                self.status |= 0x10;
131                &mut self.buf[3]
132            },
133            _ => unreachable!(),
134        }
135    }
136    pub fn flush(&mut self, dev: &Storage<impl BlockDevice>, start: u32) -> Result<(), DeviceError> {
137        let s = self.status;
138        self.status = s & 0xF;
139        match s {
140            // Contiguous
141            // ABCD
142            v if (v >> 4) == 0xF => return dev.write(&self.buf, start),
143            // ABC
144            v if (v >> 4) == 0xE => return dev.write(&self.buf[0..3], start),
145            // AB
146            v if (v >> 4) == 0xC => return dev.write(&self.buf[0..2], start),
147            // CD
148            v if (v >> 4) == 0x3 => return dev.write(&self.buf[2..], start + 2),
149            // BCD
150            v if (v >> 4) == 0x7 => return dev.write(&self.buf[1..], start + 1),
151            // BC
152            v if (v >> 4) == 0x6 => return dev.write(&self.buf[1..3], start + 1),
153            // Singles
154            // D
155            v if (v >> 4) == 1 => return dev.write_single(&self.buf[3], start + 3),
156            // C
157            v if (v >> 4) == 2 => return dev.write_single(&self.buf[2], start + 2),
158            // B
159            v if (v >> 4) == 4 => return dev.write_single(&self.buf[1], start + 1),
160            // A
161            v if (v >> 4) == 8 => return dev.write_single(&self.buf[0], start),
162            _ => (),
163        }
164        // A
165        if s & 0x80 != 0 {
166            dev.write_single(&self.buf[0], start)?;
167        }
168        // B
169        if s & 0x40 != 0 {
170            dev.write_single(&self.buf[1], start + 1)?;
171        }
172        // C
173        if s & 0x20 != 0 {
174            dev.write_single(&self.buf[2], start + 2)?;
175        }
176        // D
177        if s & 0x10 != 0 {
178            dev.write_single(&self.buf[3], start + 3)?;
179        }
180        Ok(())
181    }
182    #[inline]
183    pub fn read(&mut self, dev: &Storage<impl BlockDevice>, count: u8, start: u32) -> Result<(), DeviceError> {
184        let n = cmp::min(count, BlockBuffer::COUNT);
185        dev.read(&mut self.buf[0..n as usize], start)?;
186        self.status = match n {
187            4 => 0xF,
188            3 => 0xE,
189            2 => 0xC,
190            1 => 0x8,
191            _ => unreachable!(),
192        };
193        Ok(())
194    }
195}
196impl BlockEntryIter {
197    #[inline(always)]
198    pub fn new(count: u8) -> BlockEntryIter {
199        BlockEntryIter {
200            count,
201            buf: BlockBuffer::new(),
202            prev: None,
203            last: 0u32,
204        }
205    }
206
207    #[inline(always)]
208    pub fn pos(&self) -> u32 {
209        self.prev.unwrap_or(0)
210    }
211    #[inline(always)]
212    pub fn is_loaded(&self) -> bool {
213        self.prev.is_none()
214    }
215    #[inline(always)]
216    pub fn in_scope(&self, pos: u32) -> bool {
217        (pos - self.pos()) < BlockBuffer::COUNT as u32
218    }
219    #[inline(always)]
220    pub fn buffer(&mut self, pos: u32) -> &mut [u8] {
221        self.buf.buffer((pos - self.pos()) as u8)
222    }
223    #[inline]
224    pub fn flush(&mut self, dev: &Storage<impl BlockDevice>) -> Result<(), DeviceError> {
225        if let Some(v) = self.prev.take() {
226            self.buf.flush(dev, v)?;
227        }
228        Ok(())
229    }
230    pub fn load(&mut self, dev: &Storage<impl BlockDevice>, pos: u32) -> Result<(), DeviceError> {
231        if self.last != 0 && pos < self.last {
232            return Ok(());
233        }
234        let i = cmp::min(self.count, BlockBuffer::COUNT);
235        self.buf.read(dev, i, pos)?;
236        self.last = self.last.saturating_add(i as u32);
237        self.count = self.count.saturating_sub(i);
238        self.prev = Some(pos);
239        Ok(())
240    }
241    #[inline]
242    pub fn load_and_flush(&mut self, dev: &Storage<impl BlockDevice>, pos: u32) -> Result<(), DeviceError> {
243        self.flush(dev)?;
244        self.load(dev, pos)
245    }
246}
247
248impl Deref for Block {
249    type Target = [u8];
250
251    #[inline(always)]
252    fn deref(&self) -> &[u8] {
253        &self.0
254    }
255}
256impl Default for Block {
257    #[inline]
258    fn default() -> Block {
259        Block([0u8; 0x200])
260    }
261}
262impl DerefMut for Block {
263    #[inline(always)]
264    fn deref_mut(&mut self) -> &mut [u8] {
265        &mut self.0
266    }
267}
268
269impl Default for BlockCache {
270    #[inline(always)]
271    fn default() -> BlockCache {
272        BlockCache(None)
273    }
274}
275
276impl Default for BlockBuffer {
277    #[inline]
278    fn default() -> BlockBuffer {
279        BlockBuffer::new()
280    }
281}