1use crate::otbn::{Client, Otbn};
9use core::cell::Cell;
10use kernel::collections::list::{ListLink, ListNode};
11use kernel::utilities::cells::OptionalCell;
12use kernel::ErrorCode;
13
14pub struct VirtualMuxAccel<'a> {
15 mux: &'a MuxAccel<'a>,
16 next: ListLink<'a, VirtualMuxAccel<'a>>,
17 client: OptionalCell<&'a dyn Client<'a>>,
18 id: u32,
19}
20
21impl<'a> ListNode<'a, VirtualMuxAccel<'a>> for VirtualMuxAccel<'a> {
22 fn next(&self) -> &'a ListLink<VirtualMuxAccel<'a>> {
23 &self.next
24 }
25}
26
27impl<'a> VirtualMuxAccel<'a> {
28 pub fn new(mux_accel: &'a MuxAccel<'a>) -> VirtualMuxAccel<'a> {
29 let id = mux_accel.next_id.get();
30 mux_accel.next_id.set(id + 1);
31
32 VirtualMuxAccel {
33 mux: mux_accel,
34 next: ListLink::empty(),
35 client: OptionalCell::empty(),
36 id,
37 }
38 }
39
40 pub fn set_client(&'a self, client: &'a dyn Client<'a>) {
41 self.client.set(client);
42 }
43
44 pub fn load_binary(&self, input: &[u8]) -> Result<(), ErrorCode> {
45 if !self.mux.running.get() {
47 self.mux.running.set(true);
48 self.mux.running_id.set(self.id);
49 self.mux.accel.load_binary(input)
50 } else if self.mux.running_id.get() == self.id {
51 self.mux.accel.load_binary(input)
52 } else {
53 Err(ErrorCode::BUSY)
54 }
55 }
56
57 pub fn load_data(&self, address: usize, data: &[u8]) -> Result<(), ErrorCode> {
58 if !self.mux.running.get() {
60 self.mux.running.set(true);
61 self.mux.running_id.set(self.id);
62 self.mux.accel.load_data(address, data)
63 } else if self.mux.running_id.get() == self.id {
64 self.mux.accel.load_data(address, data)
65 } else {
66 Err(ErrorCode::BUSY)
67 }
68 }
69
70 pub fn run(
71 &self,
72 address: usize,
73 output: &'static mut [u8],
74 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
75 if !self.mux.running.get() {
77 self.mux.running.set(true);
78 self.mux.running_id.set(self.id);
79 self.mux.accel.run(address, output)
80 } else if self.mux.running_id.get() == self.id {
81 self.mux.accel.run(address, output)
82 } else {
83 Err((ErrorCode::BUSY, output))
84 }
85 }
86
87 pub fn clear_data(&self) {
90 if self.mux.running_id.get() == self.id {
91 self.mux.running.set(false);
92 self.mux.accel.clear_data()
93 }
94 }
95}
96
97impl<'a> Client<'a> for VirtualMuxAccel<'a> {
98 fn op_done(&'a self, result: Result<(), ErrorCode>, output: &'static mut [u8]) {
99 self.client
100 .map(move |client| client.op_done(result, output));
101 }
102}
103
104pub struct MuxAccel<'a> {
110 accel: &'a Otbn<'a>,
111 running: Cell<bool>,
112 running_id: Cell<u32>,
113 next_id: Cell<u32>,
114}
115
116impl<'a> MuxAccel<'a> {
117 pub const fn new(accel: &'a Otbn<'a>) -> MuxAccel<'a> {
118 MuxAccel {
119 accel,
120 running: Cell::new(false),
121 running_id: Cell::new(0),
122 next_id: Cell::new(0),
123 }
124 }
125}