Skip to main content

strat9_bus_drivers/
moxtet.rs

1use 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    /// Builds this from raw.
21    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    /// Performs the name operation.
34    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    /// Creates a new instance.
63    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    /// Performs the discover topology operation.
75    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    /// Performs the module read operation.
93    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    /// Performs the module write operation.
101    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    /// Sets irq mask.
110    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    /// Performs the name operation.
119    fn name(&self) -> &str {
120        "moxtet"
121    }
122
123    /// Performs the compatible operation.
124    fn compatible(&self) -> &[&str] {
125        COMPATIBLE
126    }
127
128    /// Requires explicit SPI backend configuration; no auto-detect.
129    fn probe(&self) -> bool {
130        false
131    }
132
133    /// Performs the init operation.
134    fn init(&mut self, _base: usize) -> Result<(), BusError> {
135        self.power_state = PowerState::On;
136        Ok(())
137    }
138
139    /// Performs the shutdown operation.
140    fn shutdown(&mut self) -> Result<(), BusError> {
141        self.power_state = PowerState::Off;
142        Ok(())
143    }
144
145    /// Reads reg.
146    fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
147        self.module_read(offset).map(|v| v as u32)
148    }
149
150    /// Writes reg.
151    fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
152        self.module_write(offset, value as u8)
153    }
154
155    /// Performs the children operation.
156    fn children(&self) -> Vec<BusChild> {
157        self.modules
158            .iter()
159            .map(|m| BusChild {
160                name: String::from(m.id.name()),
161                base_addr: m.index as u64,
162                size: 1,
163            })
164            .collect()
165    }
166
167    /// Handles irq.
168    fn handle_irq(&mut self) -> bool {
169        for i in 0..self.module_count {
170            if self.irq_mask[i] {
171                continue;
172            }
173            let status = self.rx_buf[i + 1];
174            if status & 0xF0 != 0 {
175                return true;
176            }
177        }
178        false
179    }
180}