strat9_bus_drivers/
mips_cdmm.rs1use crate::{BusChild, BusDriver, BusError, PowerState, mmio::MmioRegion};
2use alloc::{string::String, vec::Vec};
3
4const CDMM_DRB_SIZE: usize = 64;
5
6const CDMM_ACSR_DEVTYPE_SHIFT: u32 = 24;
7const CDMM_ACSR_DEVTYPE_MASK: u32 = 0xFF << CDMM_ACSR_DEVTYPE_SHIFT;
8const CDMM_ACSR_DEVSIZE_SHIFT: u32 = 16;
9const CDMM_ACSR_DEVSIZE_MASK: u32 = 0x1F << CDMM_ACSR_DEVSIZE_SHIFT;
10const CDMM_ACSR_DEVREV_SHIFT: u32 = 12;
11const CDMM_ACSR_DEVREV_MASK: u32 = 0xF << CDMM_ACSR_DEVREV_SHIFT;
12const CDMM_ACSR_UW: u32 = 1 << 3;
13const CDMM_ACSR_UR: u32 = 1 << 2;
14const CDMM_ACSR_SW: u32 = 1 << 1;
15const CDMM_ACSR_SR: u32 = 1 << 0;
16
17const MAX_DRBS: usize = 256;
18
19const COMPATIBLE: &[&str] = &["mti,mips-cdmm"];
20
21#[derive(Debug, Clone)]
22pub struct CdmmDevice {
23 pub dev_type: u8,
24 pub dev_size: u8,
25 pub dev_rev: u8,
26 pub drb_offset: usize,
27 pub user_write: bool,
28 pub user_read: bool,
29 pub super_write: bool,
30 pub super_read: bool,
31}
32
33pub struct MipsCdmm {
34 regs: MmioRegion,
35 devices: Vec<CdmmDevice>,
36 total_drbs: usize,
37 power_state: PowerState,
38}
39
40impl MipsCdmm {
41 pub fn new() -> Self {
43 Self {
44 regs: MmioRegion::new(),
45 devices: Vec::new(),
46 total_drbs: 0,
47 power_state: PowerState::Off,
48 }
49 }
50
51 pub fn discover_devices(&mut self) {
53 self.devices.clear();
54 if !self.regs.is_valid() {
55 return;
56 }
57
58 let mut drb = 0;
59 while drb < MAX_DRBS {
60 let offset = drb * CDMM_DRB_SIZE;
61 let acsr = self.regs.read32(offset);
62
63 let dev_type = ((acsr & CDMM_ACSR_DEVTYPE_MASK) >> CDMM_ACSR_DEVTYPE_SHIFT) as u8;
64 let dev_size = ((acsr & CDMM_ACSR_DEVSIZE_MASK) >> CDMM_ACSR_DEVSIZE_SHIFT) as u8;
65 let dev_rev = ((acsr & CDMM_ACSR_DEVREV_MASK) >> CDMM_ACSR_DEVREV_SHIFT) as u8;
66
67 if dev_type == 0 {
68 break;
69 }
70
71 let block_count = if dev_size == 0 { 1 } else { dev_size as usize };
72
73 self.devices.push(CdmmDevice {
74 dev_type,
75 dev_size,
76 dev_rev,
77 drb_offset: offset,
78 user_write: (acsr & CDMM_ACSR_UW) != 0,
79 user_read: (acsr & CDMM_ACSR_UR) != 0,
80 super_write: (acsr & CDMM_ACSR_SW) != 0,
81 super_read: (acsr & CDMM_ACSR_SR) != 0,
82 });
83
84 drb += block_count;
85 }
86
87 self.total_drbs = drb;
88 }
89
90 pub fn device_read32(&self, dev_index: usize, offset: usize) -> Result<u32, BusError> {
92 let dev = self
93 .devices
94 .get(dev_index)
95 .ok_or(BusError::DeviceNotFound)?;
96 self.regs.check_user_offset(dev.drb_offset + offset)?;
100 Ok(self.regs.read32(dev.drb_offset + offset))
101 }
102
103 pub fn device_write32(
105 &self,
106 dev_index: usize,
107 offset: usize,
108 val: u32,
109 ) -> Result<(), BusError> {
110 let dev = self
111 .devices
112 .get(dev_index)
113 .ok_or(BusError::DeviceNotFound)?;
114 self.regs.check_user_offset(dev.drb_offset + offset)?;
115 self.regs.write32(dev.drb_offset + offset, val);
116 Ok(())
117 }
118}
119
120impl BusDriver for MipsCdmm {
121 fn name(&self) -> &str {
123 "mips-cdmm"
124 }
125
126 fn compatible(&self) -> &[&str] {
128 COMPATIBLE
129 }
130
131 fn init(&mut self, base: usize) -> Result<(), BusError> {
133 self.regs.init(base, MAX_DRBS * CDMM_DRB_SIZE);
134 self.discover_devices();
135 self.power_state = PowerState::On;
136 Ok(())
137 }
138
139 fn shutdown(&mut self) -> Result<(), BusError> {
141 self.power_state = PowerState::Off;
142 Ok(())
143 }
144
145 fn read_reg(&self, offset: usize) -> Result<u32, BusError> {
147 if !self.regs.is_valid() {
148 return Err(BusError::InitFailed);
149 }
150 self.regs.check_user_offset(offset)?;
151 Ok(self.regs.read32(offset))
152 }
153
154 fn write_reg(&mut self, offset: usize, value: u32) -> Result<(), BusError> {
156 if !self.regs.is_valid() {
157 return Err(BusError::InitFailed);
158 }
159 self.regs.check_user_offset(offset)?;
160 self.regs.write32(offset, value);
161 Ok(())
162 }
163
164 fn children(&self) -> Vec<BusChild> {
166 self.devices
167 .iter()
168 .enumerate()
169 .map(|(i, d)| BusChild {
170 name: alloc::format!("cdmm-dev-{:02x}", d.dev_type),
171 base_addr: d.drb_offset as u64,
172 size: (d.dev_size.max(1) as u64) * (CDMM_DRB_SIZE as u64),
173 })
174 .collect()
175 }
176}