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