strat9_bus_drivers/
moxtet.rs1use crate::{BusChild, BusDriver, BusError, PowerState};
2use alloc::{string::String, vec::Vec};
3
4const MAX_MODULES: usize = 6;
5
6const COMPATIBLE: &[&str] = &["cznic,moxtet"];
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum MoxtetModuleId {
10 Sfp,
11 Pci,
12 Topaz,
13 Peridot,
14 Usb3,
15 PcieBridge,
16 Unknown(u8),
17}
18
19impl MoxtetModuleId {
20 pub fn from_raw(raw: u8) -> Self {
22 match raw & 0x0F {
23 0x01 => MoxtetModuleId::Sfp,
24 0x02 => MoxtetModuleId::Pci,
25 0x03 => MoxtetModuleId::Topaz,
26 0x04 => MoxtetModuleId::Peridot,
27 0x05 => MoxtetModuleId::Usb3,
28 0x06 => MoxtetModuleId::PcieBridge,
29 other => MoxtetModuleId::Unknown(other),
30 }
31 }
32
33 pub fn name(&self) -> &'static str {
35 match self {
36 MoxtetModuleId::Sfp => "sfp",
37 MoxtetModuleId::Pci => "pci",
38 MoxtetModuleId::Topaz => "topaz",
39 MoxtetModuleId::Peridot => "peridot",
40 MoxtetModuleId::Usb3 => "usb3",
41 MoxtetModuleId::PcieBridge => "pcie-bridge",
42 MoxtetModuleId::Unknown(_) => "unknown",
43 }
44 }
45}
46
47pub struct MoxtetModule {
49 pub id: MoxtetModuleId,
50 pub index: u8,
54}
55
56pub struct Moxtet {
73 modules: Vec<MoxtetModule>,
74 module_count: usize,
75 tx_buf: [u8; MAX_MODULES + 1],
76 rx_buf: [u8; MAX_MODULES + 1],
77 irq_mask: [bool; MAX_MODULES],
78 power_state: PowerState,
79}
80
81impl Moxtet {
82 pub fn new() -> Self {
84 Self {
85 modules: Vec::new(),
86 module_count: 0,
87 tx_buf: [0; MAX_MODULES + 1],
88 rx_buf: [0; MAX_MODULES + 1],
89 irq_mask: [false; MAX_MODULES],
90 power_state: PowerState::Off,
91 }
92 }
93
94 pub fn discover_topology(&mut self, spi_data: &[u8]) {
96 self.modules.clear();
97 self.module_count = 0;
98
99 for (i, &byte) in spi_data.iter().enumerate().skip(1) {
100 if i > MAX_MODULES {
101 break;
102 }
103 let id = MoxtetModuleId::from_raw(byte);
104 self.modules.push(MoxtetModule {
105 id,
106 index: (i - 1) as u8,
107 });
108 self.module_count = i;
109 }
110 }
111
112 pub fn module_read(&self, index: usize) -> Result<u8, BusError> {
114 if index >= self.module_count {
115 return Err(BusError::DeviceNotFound);
116 }
117 Ok(self.rx_buf[index + 1])
118 }
119
120 pub fn module_write(&mut self, index: usize, value: u8) -> Result<(), BusError> {
122 if index >= self.module_count {
123 return Err(BusError::DeviceNotFound);
124 }
125 self.tx_buf[index + 1] = value;
126 Ok(())
127 }
128
129 pub fn set_irq_mask(&mut self, index: usize, masked: bool) {
131 if index < MAX_MODULES {
132 self.irq_mask[index] = masked;
133 }
134 }
135}
136
137impl BusDriver for Moxtet {
138 fn name(&self) -> &str {
140 "moxtet"
141 }
142
143 fn compatible(&self) -> &[&str] {
145 COMPATIBLE
146 }
147
148 fn probe(&self) -> bool {
150 false
151 }
152
153 fn init(&mut self, _base: usize) -> Result<(), BusError> {
155 self.power_state = PowerState::On;
156 Ok(())
157 }
158
159 fn shutdown(&mut self) -> Result<(), BusError> {
161 self.power_state = PowerState::Off;
162 Ok(())
163 }
164
165 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
170 self.module_read(offset).map(|v| v as u32)
171 }
172
173 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
180 self.module_write(offset, value as u8)
181 }
182
183 fn children(&self) -> Vec<BusChild> {
185 self.modules
186 .iter()
187 .map(|m| BusChild {
188 name: String::from(m.id.name()),
189 base_addr: m.index as u64,
190 size: 1,
191 })
192 .collect()
193 }
194
195 fn handle_irq(&mut self) -> bool {
197 for i in 0..self.module_count {
198 if self.irq_mask[i] {
199 continue;
200 }
201 let status = self.rx_buf[i + 1];
202 if status & 0xF0 != 0 {
203 return true;
204 }
205 }
206 false
207 }
208}