1pub mod base_address;
4mod error;
5
6use devmem::Mapping;
7use error::MappingError;
8
9use crate::protocol::{MemoryMapped, OcsdDevice, OcsdHeader};
10
11const OCSD_HEADER_SIZE: usize = 0x40;
12
13pub struct OcsdContext {
15 header_mapping: Mapping,
16 pub device_mappings: Vec<OcsdDeviceContext>,
19}
20
21pub struct OcsdDeviceContext {
23 mapping: Mapping,
24 device_size: u8,
25}
26
27impl OcsdHeader {
28 fn open_device_mapping(&self, device_index: u8) -> Result<Mapping, MappingError> {
29 if device_index >= self.max_option_cards {
30 return Err(MappingError::new(format!(
31 "requested device index {} doesn't fit max number of option cards {}",
32 device_index, self.max_option_cards
33 )));
34 }
35 let start_address = self.buffer_start_address as usize
36 + (self.one_option_card_size as usize * device_index as usize);
37 unsafe {
38 Mapping::new(start_address, self.one_option_card_size as usize).map_err(|_| {
39 MappingError::new(format!(
40 "unable to open device mapping at {:x}",
41 start_address
42 ))
43 })
44 }
45 }
46}
47
48impl OcsdContext {
49 pub fn new(base_address: usize) -> Result<Self, MappingError> {
53 let header_mapping_result = unsafe { Mapping::new(base_address, OCSD_HEADER_SIZE) };
54 match header_mapping_result {
55 Ok(mut header_mapping) => {
56 let init_header = Self::_read_header(&mut header_mapping);
57 let mut device_mappings: Vec<OcsdDeviceContext> = Vec::new();
58
59 for i in 0..init_header.max_option_cards {
60 match init_header.open_device_mapping(i) {
61 Ok(device_mapping) => device_mappings.push(OcsdDeviceContext {
62 mapping: device_mapping,
63 device_size: init_header.one_option_card_size,
64 }),
65 Err(e) => return Err(e),
66 }
67 }
68
69 Ok(Self {
70 header_mapping,
71 device_mappings,
72 })
73 }
74 Err(_) => Err(MappingError::new(format!(
75 "unable to open ocsd header at {:x}",
76 base_address
77 ))),
78 }
79 }
80
81 fn _read_header(header_mapping: &mut Mapping) -> OcsdHeader {
82 let mut header_data: Vec<u8> = vec![0x00; OCSD_HEADER_SIZE];
83 header_mapping.copy_into_slice(&mut header_data);
84 OcsdHeader::from_bytes(&header_data)
85 }
86
87 pub fn read_header(&mut self) -> OcsdHeader {
89 Self::_read_header(&mut self.header_mapping)
90 }
91
92 pub fn write_header(&mut self, device: &OcsdHeader) {
94 self.header_mapping.copy_from_slice(&device.to_bytes());
95 }
96}
97
98impl OcsdDeviceContext {
99 pub fn read(&mut self) -> OcsdDevice {
101 let mut device_data: Vec<u8> = vec![0x00; self.device_size as usize];
102 self.mapping.copy_into_slice(&mut device_data);
103 OcsdDevice::from_bytes(&device_data)
104 }
105
106 pub fn write(&mut self, device: &OcsdDevice) {
108 self.mapping.copy_from_slice(&device.to_bytes());
109 }
110}