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 {
48 pub id: MoxtetModuleId,
49 pub index: u8,
50}
51
52pub struct Moxtet {
53 modules: Vec<MoxtetModule>,
54 module_count: usize,
55 tx_buf: [u8; MAX_MODULES + 1],
56 rx_buf: [u8; MAX_MODULES + 1],
57 irq_mask: [bool; MAX_MODULES],
58 power_state: PowerState,
59}
60
61impl Moxtet {
62 pub fn new() -> Self {
64 Self {
65 modules: Vec::new(),
66 module_count: 0,
67 tx_buf: [0; MAX_MODULES + 1],
68 rx_buf: [0; MAX_MODULES + 1],
69 irq_mask: [false; MAX_MODULES],
70 power_state: PowerState::Off,
71 }
72 }
73
74 pub fn discover_topology(&mut self, spi_data: &[u8]) {
76 self.modules.clear();
77 self.module_count = 0;
78
79 for (i, &byte) in spi_data.iter().enumerate().skip(1) {
80 if i > MAX_MODULES {
81 break;
82 }
83 let id = MoxtetModuleId::from_raw(byte);
84 self.modules.push(MoxtetModule {
85 id,
86 index: (i - 1) as u8,
87 });
88 self.module_count = i;
89 }
90 }
91
92 pub fn module_read(&self, index: usize) -> Result<u8, BusError> {
94 if index >= self.module_count {
95 return Err(BusError::DeviceNotFound);
96 }
97 Ok(self.rx_buf[index + 1])
98 }
99
100 pub fn module_write(&mut self, index: usize, value: u8) -> Result<(), BusError> {
102 if index >= self.module_count {
103 return Err(BusError::DeviceNotFound);
104 }
105 self.tx_buf[index + 1] = value;
106 Ok(())
107 }
108
109 pub fn set_irq_mask(&mut self, index: usize, masked: bool) {
111 if index < MAX_MODULES {
112 self.irq_mask[index] = masked;
113 }
114 }
115}
116
117impl BusDriver for Moxtet {
118 fn name(&self) -> &str {
120 "moxtet"
121 }
122
123 fn compatible(&self) -> &[&str] {
125 COMPATIBLE
126 }
127
128 fn init(&mut self, _base: usize) -> Result<(), BusError> {
130 self.power_state = PowerState::On;
131 Ok(())
132 }
133
134 fn shutdown(&mut self) -> Result<(), BusError> {
136 self.power_state = PowerState::Off;
137 Ok(())
138 }
139
140 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
142 self.module_read(offset).map(|v| v as u32)
143 }
144
145 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
147 self.module_write(offset, value as u8)
148 }
149
150 fn children(&self) -> Vec<BusChild> {
152 self.modules
153 .iter()
154 .map(|m| BusChild {
155 name: String::from(m.id.name()),
156 base_addr: m.index as u64,
157 size: 1,
158 })
159 .collect()
160 }
161
162 fn handle_irq(&mut self) -> bool {
164 for i in 0..self.module_count {
165 if self.irq_mask[i] {
166 continue;
167 }
168 let status = self.rx_buf[i + 1];
169 if status & 0xF0 != 0 {
170 return true;
171 }
172 }
173 false
174 }
175}