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}
42pub struct BlockCache(Option<u32>);
43pub struct Block([u8; Block::SIZE]);
44
45impl Block {
46    pub const SIZE: usize = 0x200;
47
48    #[inline]
49    pub fn new() -> Block {
50        Block([0u8; 0x200])
51    }
52
53    #[inline(always)]
54    pub fn clear(&mut self) {
55        self.0.fill(0)
56    }
57}
58impl BlockCache {
59    #[inline(always)]
60    pub fn new() -> BlockCache {
61        BlockCache(None)
62    }
63
64    #[inline(always)]
65    pub fn clear(&mut self) {
66        self.0.take();
67    }
68    #[inline]
69    pub fn read_single(&mut self, dev: &Storage<impl BlockDevice>, b: &mut Block, pos: u32) -> Result<(), DeviceError> {
70        match self.0.replace(pos) {
71            Some(v) if v != pos => dev.read_single(b, pos),
72            None => dev.read_single(b, pos),
73            _ => Ok(()),
74        }
75    }
76}
77impl BlockBuffer {
78    pub const COUNT: u8 = 0x4u8;
79    pub const SLOT_A: u8 = 0x0u8;
80    pub const SLOT_B: u8 = 0x1u8;
81    pub const SLOT_C: u8 = 0x2u8;
82    pub const SLOT_D: u8 = 0x3u8;
83
84    #[inline]
85    pub fn new() -> BlockBuffer {
86        BlockBuffer {
87            buf:    [Block::new(), Block::new(), Block::new(), Block::new()],
88            status: 0u8,
89        }
90    }
91
92    #[inline]
93    pub fn is_dirty(&self, slot: u8) -> bool {
94        match slot % BlockBuffer::COUNT {
95            BlockBuffer::SLOT_A if self.status & 0x80 != 0 => true,
96            BlockBuffer::SLOT_B if self.status & 0x40 != 0 => true,
97            BlockBuffer::SLOT_C if self.status & 0x20 != 0 => true,
98            BlockBuffer::SLOT_D if self.status & 0x10 != 0 => true,
99            _ => false,
100        }
101    }
102    #[inline]
103    pub fn is_loaded(&self, slot: u8) -> bool {
104        match slot % BlockBuffer::COUNT {
105            BlockBuffer::SLOT_A if self.status & 0x8 != 0 => true,
106            BlockBuffer::SLOT_B if self.status & 0x4 != 0 => true,
107            BlockBuffer::SLOT_C if self.status & 0x2 != 0 => true,
108            BlockBuffer::SLOT_D if self.status & 0x1 != 0 => true,
109            _ => false,
110        }
111    }
112    #[inline]
113    pub fn buffer(&mut self, slot: u8) -> &mut [u8] {
114        match slot % BlockBuffer::COUNT {
115            BlockBuffer::SLOT_A => {
116                self.status |= 0x80;
117                &mut self.buf[0]
118            },
119            BlockBuffer::SLOT_B => {
120                self.status |= 0x40;
121                &mut self.buf[1]
122            },
123            BlockBuffer::SLOT_C => {
124                self.status |= 0x20;
125                &mut self.buf[2]
126            },
127            BlockBuffer::SLOT_D => {
128                self.status |= 0x10;
129                &mut self.buf[3]
130            },
131            _ => unreachable!(),
132        }
133    }
134    pub fn flush(&mut self, dev: &Storage<impl BlockDevice>, start: u32) -> Result<(), DeviceError> {
135        let s = self.status;
136        self.status = s & 0xF;
137        match s {
138            // Contiguous
139            // ABCD
140            v if (v >> 4) == 0xF => return dev.write(&self.buf, start),
141            // ABC
142            v if (v >> 4) == 0xE => return dev.write(&self.buf[0..3], start),
143            // AB
144            v if (v >> 4) == 0xC => return dev.write(&self.buf[0..2], start),
145            // CD
146            v if (v >> 4) == 0x3 => return dev.write(&self.buf[2..], start + 2),
147            // BCD
148            v if (v >> 4) == 0x7 => return dev.write(&self.buf[1..], start + 1),
149            // BC
150            v if (v >> 4) == 0x6 => return dev.write(&self.buf[1..3], start + 1),
151            // Singles
152            // D
153            v if (v >> 4) == 1 => return dev.write_single(&self.buf[3], start + 3),
154            // C
155            v if (v >> 4) == 2 => return dev.write_single(&self.buf[2], start + 2),
156            // B
157            v if (v >> 4) == 4 => return dev.write_single(&self.buf[1], start + 1),
158            // A
159            v if (v >> 4) == 8 => return dev.write_single(&self.buf[0], start),
160            _ => (),
161        }
162        // A
163        if s & 0x80 != 0 {
164            dev.write_single(&self.buf[0], start)?;
165        }
166        // B
167        if s & 0x40 != 0 {
168            dev.write_single(&self.buf[1], start + 1)?;
169        }
170        // C
171        if s & 0x20 != 0 {
172            dev.write_single(&self.buf[2], start + 2)?;
173        }
174        // D
175        if s & 0x10 != 0 {
176            dev.write_single(&self.buf[3], start + 3)?;
177        }
178        Ok(())
179    }
180    #[inline]
181    pub fn read(&mut self, dev: &Storage<impl BlockDevice>, count: u8, start: u32) -> Result<(), DeviceError> {
182        let n = cmp::min(count, BlockBuffer::COUNT);
183        dev.read(&mut self.buf[0..n as usize], start)?;
184        self.status = match n {
185            4 => 0xF,
186            3 => 0xE,
187            2 => 0xC,
188            1 => 0x8,
189            _ => unreachable!(),
190        };
191        Ok(())
192    }
193}
194impl BlockEntryIter {
195    #[inline(always)]
196    pub fn new(count: u8) -> BlockEntryIter {
197        BlockEntryIter {
198            count,
199            buf: BlockBuffer::new(),
200            prev: None,
201            last: 0u32,
202        }
203    }
204
205    #[inline(always)]
206    pub fn pos(&self) -> u32 {
207        self.prev.unwrap_or(0)
208    }
209    #[inline(always)]
210    pub fn is_loaded(&self) -> bool {
211        self.prev.is_none()
212    }
213    #[inline(always)]
214    pub fn in_scope(&self, pos: u32) -> bool {
215        (pos - self.pos()) < BlockBuffer::COUNT as u32
216    }
217    #[inline(always)]
218    pub fn buffer(&mut self, pos: u32) -> &mut [u8] {
219        self.buf.buffer((pos - self.pos()) as u8)
220    }
221    #[inline]
222    pub fn flush(&mut self, dev: &Storage<impl BlockDevice>) -> Result<(), DeviceError> {
223        if let Some(v) = self.prev.take() {
224            self.buf.flush(dev, v)?;
225        }
226        Ok(())
227    }
228    pub fn load(&mut self, dev: &Storage<impl BlockDevice>, pos: u32) -> Result<(), DeviceError> {
229        if self.last != 0 && pos < self.last {
230            return Ok(());
231        }
232        let i = cmp::min(self.count, BlockBuffer::COUNT);
233        self.buf.read(dev, i, pos)?;
234        self.last = self.last.saturating_add(i as u32);
235        self.count = self.count.saturating_sub(i);
236        self.prev = Some(pos);
237        Ok(())
238    }
239    #[inline]
240    pub fn load_and_flush(&mut self, dev: &Storage<impl BlockDevice>, pos: u32) -> Result<(), DeviceError> {
241        self.flush(dev)?;
242        self.load(dev, pos)
243    }
244}
245
246impl Deref for Block {
247    type Target = [u8];
248
249    #[inline(always)]
250    fn deref(&self) -> &[u8] {
251        &self.0
252    }
253}
254impl Default for Block {
255    #[inline]
256    fn default() -> Block {
257        Block([0u8; 0x200])
258    }
259}
260impl DerefMut for Block {
261    #[inline(always)]
262    fn deref_mut(&mut self) -> &mut [u8] {
263        &mut self.0
264    }
265}
266
267impl Default for BlockCache {
268    #[inline(always)]
269    fn default() -> BlockCache {
270        BlockCache(None)
271    }
272}
273
274impl Default for BlockBuffer {
275    #[inline]
276    fn default() -> BlockBuffer {
277        BlockBuffer::new()
278    }
279}