1use crate::chip::{eth_addr::EthAddr, ChipInterface};
5use std::fs;
6
7#[derive(Debug)]
8pub enum FnNoc {
9 Read {
10 noc_id: u8,
11 x: u32,
12 y: u32,
13 addr: u64,
14 data: *mut u8,
15 len: u64,
16 },
17 Write {
18 noc_id: u8,
19 x: u32,
20 y: u32,
21 addr: u64,
22 data: *const u8,
23 len: u64,
24 },
25 Broadcast {
26 noc_id: u8,
27 addr: u64,
28 data: *const u8,
29 len: u64,
30 },
31}
32
33#[derive(Debug)]
34pub struct FnRemote {
35 pub addr: EthAddr,
36 pub rw: FnNoc,
37}
38
39#[derive(Debug)]
40pub enum FnAxi {
41 Read {
42 addr: u32,
43 data: *mut u8,
44 len: u32,
45 },
46 Write {
47 addr: u32,
48 data: *const u8,
49 len: u32,
50 },
51}
52
53#[derive(Clone, Debug)]
54pub struct DeviceInfo {
55 pub interface_id: u32,
56
57 pub domain: u16,
58 pub bus: u16,
59 pub slot: u16,
60 pub function: u16,
61
62 pub vendor: u16,
63 pub device_id: u16,
64 pub bar_size: u64,
65}
66
67impl DeviceInfo {
68 fn pcie_base_path(&self) -> String {
70 let domain = format!("{:04x}", self.domain);
71 let bus = format!("{:02x}", self.bus);
72 let slot = format!("{:02x}", self.slot);
73 let function = format!("{:01x}", self.function);
74 format!(
75 "/sys/bus/pci/devices/{}:{}:{}.{}/",
76 domain, bus, slot, function
77 )
78 }
79
80 fn pcie_link_width(&self, s: &str) -> u32 {
82 let base_path = self.pcie_base_path();
83 let path = format!("{}{}{}", &base_path, s, "_link_width");
84 let width = fs::read_to_string(path)
85 .map(|s| s.trim().to_string())
86 .unwrap();
87 width.parse::<u32>().unwrap()
88 }
89
90 fn pcie_link_gen(&self, s: &str) -> i32 {
92 let base_path = self.pcie_base_path();
93 let path = format!("{}{}{}", &base_path, s, "_link_speed");
94 let speed = fs::read_to_string(path)
95 .map(|s| s.trim().to_string())
96 .unwrap();
97 match speed.split_whitespace().next().unwrap_or("") {
98 "2.5" => 1,
99 "5.0" => 2,
100 "8.0" => 3,
101 "16.0" => 4,
102 "32.0" => 5,
103 "64.0" => 6,
104 _ => -1,
105 }
106 }
107
108 pub fn pcie_current_link_width(&self) -> u32 {
110 self.pcie_link_width("current")
111 }
112
113 pub fn pcie_current_link_gen(&self) -> i32 {
115 self.pcie_link_gen("current")
116 }
117
118 pub fn pcie_max_link_width(&self) -> u32 {
120 self.pcie_link_width("max")
121 }
122
123 pub fn pcie_max_link_gen(&self) -> i32 {
125 self.pcie_link_gen("max")
126 }
127}
128
129#[derive(Debug)]
130pub enum FnDriver {
131 DeviceInfo(*mut Option<DeviceInfo>),
132}
133
134#[derive(Debug)]
135pub enum FnOptions {
136 Driver(FnDriver),
137 Axi(FnAxi),
138 Noc(FnNoc),
139 Eth(FnRemote),
140}
141
142#[derive(Clone)]
143pub struct CallbackStorage<T: Clone + Send> {
144 pub callback: fn(&T, FnOptions) -> Result<(), Box<dyn std::error::Error>>,
145 pub user_data: T,
146}
147
148impl<T: Clone + Send> CallbackStorage<T> {
149 pub fn new(
150 callback: fn(&T, FnOptions) -> Result<(), Box<dyn std::error::Error>>,
151 user_data: T,
152 ) -> Self {
153 Self {
154 callback,
155 user_data,
156 }
157 }
158}
159
160impl<T: Clone + Send + 'static> ChipInterface for CallbackStorage<T> {
161 fn get_device_info(&self) -> Result<Option<DeviceInfo>, Box<dyn std::error::Error>> {
162 let mut driver_info = None;
163 (self.callback)(
164 &self.user_data,
165 FnOptions::Driver(FnDriver::DeviceInfo((&mut driver_info) as *mut _)),
166 )?;
167
168 Ok(driver_info)
169 }
170
171 fn axi_read(&self, addr: u32, data: &mut [u8]) -> Result<(), Box<dyn std::error::Error>> {
172 (self.callback)(
173 &self.user_data,
174 FnOptions::Axi(FnAxi::Read {
175 addr,
176 data: data.as_mut_ptr(),
177 len: data.len() as u32,
178 }),
179 )
180 }
181
182 fn axi_write(&self, addr: u32, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
183 (self.callback)(
184 &self.user_data,
185 FnOptions::Axi(FnAxi::Write {
186 addr,
187 data: data.as_ptr(),
188 len: data.len() as u32,
189 }),
190 )
191 }
192
193 fn noc_read(
194 &self,
195 noc_id: u8,
196 x: u8,
197 y: u8,
198 addr: u64,
199 data: &mut [u8],
200 ) -> Result<(), Box<dyn std::error::Error>> {
201 (self.callback)(
202 &self.user_data,
203 FnOptions::Noc(FnNoc::Read {
204 noc_id,
205 x: x as u32,
206 y: y as u32,
207 addr: addr as u64,
208 data: data.as_mut_ptr(),
209 len: data.len() as u64,
210 }),
211 )
212 }
213
214 fn noc_write(
215 &self,
216 noc_id: u8,
217 x: u8,
218 y: u8,
219 addr: u64,
220 data: &[u8],
221 ) -> Result<(), Box<dyn std::error::Error>> {
222 (self.callback)(
223 &self.user_data,
224 FnOptions::Noc(FnNoc::Write {
225 noc_id,
226 x: x as u32,
227 y: y as u32,
228 addr,
229 data: data.as_ptr(),
230 len: data.len() as u64,
231 }),
232 )
233 }
234
235 fn noc_broadcast(
236 &self,
237 noc_id: u8,
238 addr: u64,
239 data: &[u8],
240 ) -> Result<(), Box<dyn std::error::Error>> {
241 (self.callback)(
242 &self.user_data,
243 FnOptions::Noc(FnNoc::Broadcast {
244 noc_id,
245 addr: addr as u64,
246 data: data.as_ptr(),
247 len: data.len() as u64,
248 }),
249 )
250 }
251
252 fn eth_noc_read(
253 &self,
254 eth_addr: EthAddr,
255 noc_id: u8,
256 x: u8,
257 y: u8,
258 addr: u64,
259 data: &mut [u8],
260 ) -> Result<(), Box<dyn std::error::Error>> {
261 (self.callback)(
262 &self.user_data,
263 FnOptions::Eth(FnRemote {
264 addr: eth_addr,
265 rw: FnNoc::Read {
266 noc_id,
267 x: x as u32,
268 y: y as u32,
269 addr: addr as u64,
270 data: data.as_mut_ptr(),
271 len: data.len() as u64,
272 },
273 }),
274 )
275 }
276
277 fn eth_noc_write(
278 &self,
279 eth_addr: EthAddr,
280 noc_id: u8,
281 x: u8,
282 y: u8,
283 addr: u64,
284 data: &[u8],
285 ) -> Result<(), Box<dyn std::error::Error>> {
286 (self.callback)(
287 &self.user_data,
288 FnOptions::Eth(FnRemote {
289 addr: eth_addr,
290 rw: FnNoc::Write {
291 noc_id,
292 x: x as u32,
293 y: y as u32,
294 addr: addr as u64,
295 data: data.as_ptr(),
296 len: data.len() as u64,
297 },
298 }),
299 )
300 }
301
302 fn eth_noc_broadcast(
303 &self,
304 eth_addr: EthAddr,
305 noc_id: u8,
306 addr: u64,
307 data: &[u8],
308 ) -> Result<(), Box<dyn std::error::Error>> {
309 (self.callback)(
310 &self.user_data,
311 FnOptions::Eth(FnRemote {
312 addr: eth_addr,
313 rw: FnNoc::Broadcast {
314 noc_id,
315 addr: addr as u64,
316 data: data.as_ptr(),
317 len: data.len() as u64,
318 },
319 }),
320 )
321 }
322
323 fn as_any(&self) -> &dyn std::any::Any {
324 self
325 }
326}