blob: d4b46eb57fff1d2842268db95796e5b344e5be1c [file] [log] [blame]
Zach Reiznercce4a962017-05-03 10:40:11 -07001// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Handles routing to devices in an address space.
6
Zach Reizner55a9e502018-10-03 10:22:32 -07007use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
Zach Reiznercce4a962017-05-03 10:40:11 -07008use std::collections::btree_map::BTreeMap;
David Tolnayb4bd00f2019-02-12 17:51:26 -08009use std::fmt::{self, Display};
Zach Reiznercce4a962017-05-03 10:40:11 -070010use std::result;
David Tolnay1d4d44a2018-12-03 23:37:46 -080011use std::sync::Arc;
12
13use sync::Mutex;
Zach Reiznercce4a962017-05-03 10:40:11 -070014
15/// Trait for devices that respond to reads or writes in an arbitrary address space.
16///
17/// The device does not care where it exists in address space as each method is only given an offset
18/// into its allocated portion of address space.
19#[allow(unused_variables)]
20pub trait BusDevice: Send {
Zach Reizner3ba00982019-01-23 19:04:43 -080021 /// Returns a label suitable for debug output.
22 fn debug_label(&self) -> String;
Zach Reiznercce4a962017-05-03 10:40:11 -070023 /// Reads at `offset` from this device
24 fn read(&mut self, offset: u64, data: &mut [u8]) {}
25 /// Writes at `offset` into this device
26 fn write(&mut self, offset: u64, data: &[u8]) {}
Dylan Reidcc08cdb2018-05-24 19:30:53 +000027 /// Sets a register in the configuration space. Only used by PCI.
28 /// * `reg_idx` - The index of the config register to modify.
29 /// * `offset` - Offset in to the register.
30 fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {}
31 /// Gets a register from the configuration space. Only used by PCI.
32 /// * `reg_idx` - The index of the config register to read.
Zach Reizner55a9e502018-10-03 10:22:32 -070033 fn config_register_read(&self, reg_idx: usize) -> u32 {
34 0
35 }
Jingkui Wangf6752e72018-11-08 10:47:42 -080036 /// Invoked when the device is sandboxed.
37 fn on_sandboxed(&mut self) {}
Zach Reiznercce4a962017-05-03 10:40:11 -070038}
39
40#[derive(Debug)]
41pub enum Error {
42 /// The insertion failed because the new device overlapped with an old device.
43 Overlap,
44}
45
David Tolnayb4bd00f2019-02-12 17:51:26 -080046impl Display for Error {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 use self::Error::*;
49
50 match self {
51 Overlap => write!(f, "new device overlaps with an old device"),
52 }
53 }
54}
55
Zach Reiznercce4a962017-05-03 10:40:11 -070056pub type Result<T> = result::Result<T, Error>;
57
Dylan Reid836466a2018-05-23 17:57:05 -070058/// Holds a base and length representing the address space occupied by a `BusDevice`.
59///
60/// * base - The address at which the range start.
61/// * len - The length of the range in bytes.
62/// * full_addr - If true, return the full address from `get_device`, otherwise return the offset
63/// from `base`
Zach Reiznercce4a962017-05-03 10:40:11 -070064#[derive(Debug, Copy, Clone)]
Dylan Reid836466a2018-05-23 17:57:05 -070065pub struct BusRange {
66 pub base: u64,
67 pub len: u64,
68 pub full_addr: bool,
69}
70
71impl BusRange {
72 /// Returns true if `addr` is within the range.
73 pub fn contains(&self, addr: u64) -> bool {
74 self.base <= addr && addr < self.base + self.len
75 }
76
77 /// Returns true if there is overlap with the given range.
78 pub fn overlaps(&self, base: u64, len: u64) -> bool {
79 self.base < (base + len) && base < self.base + self.len
80 }
81}
Zach Reiznercce4a962017-05-03 10:40:11 -070082
83impl Eq for BusRange {}
84
85impl PartialEq for BusRange {
86 fn eq(&self, other: &BusRange) -> bool {
Dylan Reid836466a2018-05-23 17:57:05 -070087 self.base == other.base
Zach Reiznercce4a962017-05-03 10:40:11 -070088 }
89}
90
91impl Ord for BusRange {
92 fn cmp(&self, other: &BusRange) -> Ordering {
Dylan Reid836466a2018-05-23 17:57:05 -070093 self.base.cmp(&other.base)
Zach Reiznercce4a962017-05-03 10:40:11 -070094 }
95}
96
97impl PartialOrd for BusRange {
98 fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> {
Dylan Reid836466a2018-05-23 17:57:05 -070099 self.base.partial_cmp(&other.base)
Zach Reiznercce4a962017-05-03 10:40:11 -0700100 }
101}
102
103/// A device container for routing reads and writes over some address space.
104///
105/// This doesn't have any restrictions on what kind of device or address space this applies to. The
106/// only restriction is that no two devices can overlap in this address space.
107#[derive(Clone)]
108pub struct Bus {
David Tolnayfdac5ed2019-03-08 16:56:14 -0800109 devices: BTreeMap<BusRange, Arc<Mutex<dyn BusDevice>>>,
Zach Reiznercce4a962017-05-03 10:40:11 -0700110}
111
112impl Bus {
113 /// Constructs an a bus with an empty address space.
114 pub fn new() -> Bus {
Zach Reizner55a9e502018-10-03 10:22:32 -0700115 Bus {
116 devices: BTreeMap::new(),
117 }
Zach Reiznercce4a962017-05-03 10:40:11 -0700118 }
119
David Tolnayfdac5ed2019-03-08 16:56:14 -0800120 fn first_before(&self, addr: u64) -> Option<(BusRange, &Mutex<dyn BusDevice>)> {
Zach Reizner55a9e502018-10-03 10:22:32 -0700121 let (range, dev) = self
122 .devices
123 .range(
124 ..=BusRange {
125 base: addr,
126 len: 1,
127 full_addr: false,
128 },
David Tolnay2bac1e72018-12-12 14:33:42 -0800129 )
130 .rev()
Zach Reizner55a9e502018-10-03 10:22:32 -0700131 .next()?;
Dylan Reid836466a2018-05-23 17:57:05 -0700132 Some((*range, dev))
Zach Reiznercce4a962017-05-03 10:40:11 -0700133 }
134
David Tolnayfdac5ed2019-03-08 16:56:14 -0800135 fn get_device(&self, addr: u64) -> Option<(u64, &Mutex<dyn BusDevice>)> {
Dylan Reid836466a2018-05-23 17:57:05 -0700136 if let Some((range, dev)) = self.first_before(addr) {
137 let offset = addr - range.base;
138 if offset < range.len {
139 if range.full_addr {
140 return Some((addr, dev));
141 } else {
142 return Some((offset, dev));
143 }
Zach Reiznercce4a962017-05-03 10:40:11 -0700144 }
145 }
146 None
147 }
148
149 /// Puts the given device at the given address space.
Zach Reizner55a9e502018-10-03 10:22:32 -0700150 pub fn insert(
151 &mut self,
David Tolnayfdac5ed2019-03-08 16:56:14 -0800152 device: Arc<Mutex<dyn BusDevice>>,
Zach Reizner55a9e502018-10-03 10:22:32 -0700153 base: u64,
154 len: u64,
155 full_addr: bool,
156 ) -> Result<()> {
Zach Reiznercce4a962017-05-03 10:40:11 -0700157 if len == 0 {
158 return Err(Error::Overlap);
159 }
160
Dylan Reid836466a2018-05-23 17:57:05 -0700161 // Reject all cases where the new device's range overlaps with an existing device.
Zach Reizner55a9e502018-10-03 10:22:32 -0700162 if self
163 .devices
164 .iter()
165 .any(|(range, _dev)| range.overlaps(base, len))
166 {
Zach Reiznercce4a962017-05-03 10:40:11 -0700167 return Err(Error::Overlap);
168 }
169
Zach Reizner55a9e502018-10-03 10:22:32 -0700170 if self
171 .devices
172 .insert(
173 BusRange {
174 base,
175 len,
176 full_addr,
177 },
178 device,
David Tolnay2bac1e72018-12-12 14:33:42 -0800179 )
180 .is_some()
Zach Reizner55a9e502018-10-03 10:22:32 -0700181 {
Zach Reiznercce4a962017-05-03 10:40:11 -0700182 return Err(Error::Overlap);
183 }
184
185 Ok(())
186 }
187
188 /// Reads data from the device that owns the range containing `addr` and puts it into `data`.
189 ///
190 /// Returns true on success, otherwise `data` is untouched.
191 pub fn read(&self, addr: u64, data: &mut [u8]) -> bool {
192 if let Some((offset, dev)) = self.get_device(addr) {
David Tolnay1d4d44a2018-12-03 23:37:46 -0800193 dev.lock().read(offset, data);
Zach Reiznercce4a962017-05-03 10:40:11 -0700194 true
195 } else {
196 false
197 }
198 }
199
200 /// Writes `data` to the device that owns the range containing `addr`.
201 ///
202 /// Returns true on success, otherwise `data` is untouched.
203 pub fn write(&self, addr: u64, data: &[u8]) -> bool {
204 if let Some((offset, dev)) = self.get_device(addr) {
David Tolnay1d4d44a2018-12-03 23:37:46 -0800205 dev.lock().write(offset, data);
Zach Reiznercce4a962017-05-03 10:40:11 -0700206 true
207 } else {
208 false
209 }
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 struct DummyDevice;
Zach Reizner3ba00982019-01-23 19:04:43 -0800218 impl BusDevice for DummyDevice {
219 fn debug_label(&self) -> String {
220 "dummy device".to_owned()
221 }
222 }
Zach Reiznercce4a962017-05-03 10:40:11 -0700223
224 struct ConstantDevice;
225 impl BusDevice for ConstantDevice {
Zach Reizner3ba00982019-01-23 19:04:43 -0800226 fn debug_label(&self) -> String {
227 "constant device".to_owned()
228 }
229
Zach Reiznercce4a962017-05-03 10:40:11 -0700230 fn read(&mut self, offset: u64, data: &mut [u8]) {
231 for (i, v) in data.iter_mut().enumerate() {
232 *v = (offset as u8) + (i as u8);
233 }
234 }
235
236 fn write(&mut self, offset: u64, data: &[u8]) {
237 for (i, v) in data.iter().enumerate() {
238 assert_eq!(*v, (offset as u8) + (i as u8))
239 }
240 }
241 }
242
243 #[test]
244 fn bus_insert() {
245 let mut bus = Bus::new();
246 let dummy = Arc::new(Mutex::new(DummyDevice));
Dylan Reid836466a2018-05-23 17:57:05 -0700247 assert!(bus.insert(dummy.clone(), 0x10, 0, false).is_err());
248 assert!(bus.insert(dummy.clone(), 0x10, 0x10, false).is_ok());
249 assert!(bus.insert(dummy.clone(), 0x0f, 0x10, false).is_err());
250 assert!(bus.insert(dummy.clone(), 0x10, 0x10, false).is_err());
251 assert!(bus.insert(dummy.clone(), 0x10, 0x15, false).is_err());
252 assert!(bus.insert(dummy.clone(), 0x12, 0x15, false).is_err());
253 assert!(bus.insert(dummy.clone(), 0x12, 0x01, false).is_err());
254 assert!(bus.insert(dummy.clone(), 0x0, 0x20, false).is_err());
255 assert!(bus.insert(dummy.clone(), 0x20, 0x05, false).is_ok());
256 assert!(bus.insert(dummy.clone(), 0x25, 0x05, false).is_ok());
257 assert!(bus.insert(dummy.clone(), 0x0, 0x10, false).is_ok());
258 }
259
260 #[test]
261 fn bus_insert_full_addr() {
262 let mut bus = Bus::new();
263 let dummy = Arc::new(Mutex::new(DummyDevice));
264 assert!(bus.insert(dummy.clone(), 0x10, 0, true).is_err());
265 assert!(bus.insert(dummy.clone(), 0x10, 0x10, true).is_ok());
266 assert!(bus.insert(dummy.clone(), 0x0f, 0x10, true).is_err());
267 assert!(bus.insert(dummy.clone(), 0x10, 0x10, true).is_err());
268 assert!(bus.insert(dummy.clone(), 0x10, 0x15, true).is_err());
269 assert!(bus.insert(dummy.clone(), 0x12, 0x15, true).is_err());
270 assert!(bus.insert(dummy.clone(), 0x12, 0x01, true).is_err());
271 assert!(bus.insert(dummy.clone(), 0x0, 0x20, true).is_err());
272 assert!(bus.insert(dummy.clone(), 0x20, 0x05, true).is_ok());
273 assert!(bus.insert(dummy.clone(), 0x25, 0x05, true).is_ok());
274 assert!(bus.insert(dummy.clone(), 0x0, 0x10, true).is_ok());
Zach Reiznercce4a962017-05-03 10:40:11 -0700275 }
276
277 #[test]
278 fn bus_read_write() {
279 let mut bus = Bus::new();
280 let dummy = Arc::new(Mutex::new(DummyDevice));
Dylan Reid836466a2018-05-23 17:57:05 -0700281 assert!(bus.insert(dummy.clone(), 0x10, 0x10, false).is_ok());
Zach Reiznercce4a962017-05-03 10:40:11 -0700282 assert!(bus.read(0x10, &mut [0, 0, 0, 0]));
283 assert!(bus.write(0x10, &[0, 0, 0, 0]));
284 assert!(bus.read(0x11, &mut [0, 0, 0, 0]));
285 assert!(bus.write(0x11, &[0, 0, 0, 0]));
286 assert!(bus.read(0x16, &mut [0, 0, 0, 0]));
287 assert!(bus.write(0x16, &[0, 0, 0, 0]));
288 assert!(!bus.read(0x20, &mut [0, 0, 0, 0]));
289 assert!(!bus.write(0x20, &mut [0, 0, 0, 0]));
290 assert!(!bus.read(0x06, &mut [0, 0, 0, 0]));
291 assert!(!bus.write(0x06, &mut [0, 0, 0, 0]));
292 }
293
294 #[test]
295 fn bus_read_write_values() {
296 let mut bus = Bus::new();
297 let dummy = Arc::new(Mutex::new(ConstantDevice));
Dylan Reid836466a2018-05-23 17:57:05 -0700298 assert!(bus.insert(dummy.clone(), 0x10, 0x10, false).is_ok());
Zach Reiznercce4a962017-05-03 10:40:11 -0700299
300 let mut values = [0, 1, 2, 3];
301 assert!(bus.read(0x10, &mut values));
302 assert_eq!(values, [0, 1, 2, 3]);
303 assert!(bus.write(0x10, &values));
304 assert!(bus.read(0x15, &mut values));
305 assert_eq!(values, [5, 6, 7, 8]);
306 assert!(bus.write(0x15, &values));
307 }
Dylan Reid836466a2018-05-23 17:57:05 -0700308
309 #[test]
310 fn bus_read_write_full_addr_values() {
311 let mut bus = Bus::new();
312 let dummy = Arc::new(Mutex::new(ConstantDevice));
313 assert!(bus.insert(dummy.clone(), 0x10, 0x10, true).is_ok());
314
315 let mut values = [0u8; 4];
316 assert!(bus.read(0x10, &mut values));
317 assert_eq!(values, [0x10, 0x11, 0x12, 0x13]);
318 assert!(bus.write(0x10, &values));
319 assert!(bus.read(0x15, &mut values));
320 assert_eq!(values, [0x15, 0x16, 0x17, 0x18]);
321 assert!(bus.write(0x15, &values));
322 }
323
324 #[test]
325 fn bus_range_contains() {
Zach Reizner55a9e502018-10-03 10:22:32 -0700326 let a = BusRange {
327 base: 0x1000,
328 len: 0x400,
329 full_addr: false,
330 };
Dylan Reid836466a2018-05-23 17:57:05 -0700331 assert!(a.contains(0x1000));
332 assert!(a.contains(0x13ff));
333 assert!(!a.contains(0xfff));
334 assert!(!a.contains(0x1400));
335 assert!(a.contains(0x1200));
336 }
337
338 #[test]
339 fn bus_range_overlap() {
Zach Reizner55a9e502018-10-03 10:22:32 -0700340 let a = BusRange {
341 base: 0x1000,
342 len: 0x400,
343 full_addr: false,
344 };
Dylan Reid836466a2018-05-23 17:57:05 -0700345 assert!(a.overlaps(0x1000, 0x400));
346 assert!(a.overlaps(0xf00, 0x400));
347 assert!(a.overlaps(0x1000, 0x01));
348 assert!(a.overlaps(0xfff, 0x02));
349 assert!(a.overlaps(0x1100, 0x100));
350 assert!(a.overlaps(0x13ff, 0x100));
351 assert!(!a.overlaps(0x1400, 0x100));
352 assert!(!a.overlaps(0xf00, 0x100));
353 }
Zach Reiznercce4a962017-05-03 10:40:11 -0700354}