11853b350SSamuel Ortiz // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 21853b350SSamuel Ortiz // SPDX-License-Identifier: Apache-2.0 31853b350SSamuel Ortiz // 41853b350SSamuel Ortiz // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 51853b350SSamuel Ortiz // Use of this source code is governed by a BSD-style license that can be 6040ea543SSamuel Ortiz // found in the LICENSE-BSD-3-Clause file. 71853b350SSamuel Ortiz 81853b350SSamuel Ortiz //! Handles routing to devices in an address space. 91853b350SSamuel Ortiz 10adb318f4SRob Bradford use std::cmp::Ordering; 111853b350SSamuel Ortiz use std::collections::btree_map::BTreeMap; 121fc6d50fSRob Bradford use std::sync::{Arc, Barrier, Mutex, RwLock, Weak}; 13*a007b750SPhilipp Schuster use std::{convert, io, result}; 14*a007b750SPhilipp Schuster 15*a007b750SPhilipp Schuster use thiserror::Error; 161853b350SSamuel Ortiz 171853b350SSamuel Ortiz /// Trait for devices that respond to reads or writes in an arbitrary address space. 181853b350SSamuel Ortiz /// 191853b350SSamuel Ortiz /// The device does not care where it exists in address space as each method is only given an offset 201853b350SSamuel Ortiz /// into its allocated portion of address space. 211853b350SSamuel Ortiz #[allow(unused_variables)] 221853b350SSamuel Ortiz pub trait BusDevice: Send { 231853b350SSamuel Ortiz /// Reads at `offset` from this device read(&mut self, base: u64, offset: u64, data: &mut [u8])248173e1ccSSamuel Ortiz fn read(&mut self, base: u64, offset: u64, data: &mut [u8]) {} 251853b350SSamuel Ortiz /// Writes at `offset` into this device write(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>261fc6d50fSRob Bradford fn write(&mut self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 271fc6d50fSRob Bradford None 281fc6d50fSRob Bradford } 291853b350SSamuel Ortiz } 301853b350SSamuel Ortiz 31954f3dd0SYuanchu Xie #[allow(unused_variables)] 32954f3dd0SYuanchu Xie pub trait BusDeviceSync: Send + Sync { 33954f3dd0SYuanchu Xie /// Reads at `offset` from this device read(&self, base: u64, offset: u64, data: &mut [u8])34954f3dd0SYuanchu Xie fn read(&self, base: u64, offset: u64, data: &mut [u8]) {} 35954f3dd0SYuanchu Xie /// Writes at `offset` into this device write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>36954f3dd0SYuanchu Xie fn write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 37954f3dd0SYuanchu Xie None 38954f3dd0SYuanchu Xie } 39954f3dd0SYuanchu Xie } 40954f3dd0SYuanchu Xie 41954f3dd0SYuanchu Xie impl<B: BusDevice> BusDeviceSync for Mutex<B> { 42954f3dd0SYuanchu Xie /// Reads at `offset` from this device read(&self, base: u64, offset: u64, data: &mut [u8])43954f3dd0SYuanchu Xie fn read(&self, base: u64, offset: u64, data: &mut [u8]) { 44954f3dd0SYuanchu Xie self.lock() 45954f3dd0SYuanchu Xie .expect("Failed to acquire device lock") 46954f3dd0SYuanchu Xie .read(base, offset, data) 47954f3dd0SYuanchu Xie } 48954f3dd0SYuanchu Xie /// Writes at `offset` into this device write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>49954f3dd0SYuanchu Xie fn write(&self, base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 50954f3dd0SYuanchu Xie self.lock() 51954f3dd0SYuanchu Xie .expect("Failed to acquire device lock") 52954f3dd0SYuanchu Xie .write(base, offset, data) 53954f3dd0SYuanchu Xie } 54954f3dd0SYuanchu Xie } 55954f3dd0SYuanchu Xie 56*a007b750SPhilipp Schuster #[derive(Error, Debug)] 571853b350SSamuel Ortiz pub enum Error { 581853b350SSamuel Ortiz /// The insertion failed because the new device overlapped with an old device. 59*a007b750SPhilipp Schuster #[error("The insertion failed because the new device overlapped with an old device")] 601853b350SSamuel Ortiz Overlap, 61733e636fSSebastien Boeuf /// Failed to operate on zero sized range. 62*a007b750SPhilipp Schuster #[error("Failed to operate on zero sized range")] 63733e636fSSebastien Boeuf ZeroSizedRange, 64733e636fSSebastien Boeuf /// Failed to find address range. 65*a007b750SPhilipp Schuster #[error("Failed to find address range")] 66733e636fSSebastien Boeuf MissingAddressRange, 671853b350SSamuel Ortiz } 681853b350SSamuel Ortiz 691853b350SSamuel Ortiz pub type Result<T> = result::Result<T, Error>; 701853b350SSamuel Ortiz 71d6c68e47SSebastien Boeuf impl convert::From<Error> for io::Error { from(e: Error) -> Self72d6c68e47SSebastien Boeuf fn from(e: Error) -> Self { 73ea4693a0SJinank Jain io::Error::other(e) 74d6c68e47SSebastien Boeuf } 75d6c68e47SSebastien Boeuf } 76d6c68e47SSebastien Boeuf 7733796c4bSSamuel Ortiz /// Holds a base and length representing the address space occupied by a `BusDevice`. 7833796c4bSSamuel Ortiz /// 7933796c4bSSamuel Ortiz /// * base - The address at which the range start. 8033796c4bSSamuel Ortiz /// * len - The length of the range in bytes. 811853b350SSamuel Ortiz #[derive(Debug, Copy, Clone)] 8233796c4bSSamuel Ortiz pub struct BusRange { 8333796c4bSSamuel Ortiz pub base: u64, 8433796c4bSSamuel Ortiz pub len: u64, 8533796c4bSSamuel Ortiz } 8633796c4bSSamuel Ortiz 8733796c4bSSamuel Ortiz impl BusRange { 8833796c4bSSamuel Ortiz /// Returns true if there is overlap with the given range. overlaps(&self, base: u64, len: u64) -> bool8933796c4bSSamuel Ortiz pub fn overlaps(&self, base: u64, len: u64) -> bool { 9033796c4bSSamuel Ortiz self.base < (base + len) && base < self.base + self.len 9133796c4bSSamuel Ortiz } 9233796c4bSSamuel Ortiz } 931853b350SSamuel Ortiz 941853b350SSamuel Ortiz impl Eq for BusRange {} 951853b350SSamuel Ortiz 961853b350SSamuel Ortiz impl PartialEq for BusRange { eq(&self, other: &BusRange) -> bool971853b350SSamuel Ortiz fn eq(&self, other: &BusRange) -> bool { 9833796c4bSSamuel Ortiz self.base == other.base 991853b350SSamuel Ortiz } 1001853b350SSamuel Ortiz } 1011853b350SSamuel Ortiz 1021853b350SSamuel Ortiz impl Ord for BusRange { cmp(&self, other: &BusRange) -> Ordering1031853b350SSamuel Ortiz fn cmp(&self, other: &BusRange) -> Ordering { 10433796c4bSSamuel Ortiz self.base.cmp(&other.base) 1051853b350SSamuel Ortiz } 1061853b350SSamuel Ortiz } 1071853b350SSamuel Ortiz 1081853b350SSamuel Ortiz impl PartialOrd for BusRange { partial_cmp(&self, other: &BusRange) -> Option<Ordering>1091853b350SSamuel Ortiz fn partial_cmp(&self, other: &BusRange) -> Option<Ordering> { 110cc4422d5SRob Bradford Some(self.cmp(other)) 1111853b350SSamuel Ortiz } 1121853b350SSamuel Ortiz } 1131853b350SSamuel Ortiz 1141853b350SSamuel Ortiz /// A device container for routing reads and writes over some address space. 1151853b350SSamuel Ortiz /// 1161853b350SSamuel Ortiz /// This doesn't have any restrictions on what kind of device or address space this applies to. The 1171853b350SSamuel Ortiz /// only restriction is that no two devices can overlap in this address space. 1181870eb42SSebastien Boeuf #[derive(Default)] 1191853b350SSamuel Ortiz pub struct Bus { 120954f3dd0SYuanchu Xie devices: RwLock<BTreeMap<BusRange, Weak<dyn BusDeviceSync>>>, 1211853b350SSamuel Ortiz } 1221853b350SSamuel Ortiz 1231853b350SSamuel Ortiz impl Bus { 1241853b350SSamuel Ortiz /// Constructs an a bus with an empty address space. new() -> Bus1251853b350SSamuel Ortiz pub fn new() -> Bus { 1261853b350SSamuel Ortiz Bus { 1271870eb42SSebastien Boeuf devices: RwLock::new(BTreeMap::new()), 1281853b350SSamuel Ortiz } 1291853b350SSamuel Ortiz } 1301853b350SSamuel Ortiz first_before(&self, addr: u64) -> Option<(BusRange, Arc<dyn BusDeviceSync>)>131954f3dd0SYuanchu Xie fn first_before(&self, addr: u64) -> Option<(BusRange, Arc<dyn BusDeviceSync>)> { 1321870eb42SSebastien Boeuf let devices = self.devices.read().unwrap(); 1331870eb42SSebastien Boeuf let (range, dev) = devices 13433796c4bSSamuel Ortiz .range(..=BusRange { base: addr, len: 1 }) 13589e658d9SRob Bradford .next_back()?; 1369fc2613bSRob Bradford dev.upgrade().map(|d| (*range, d.clone())) 1371853b350SSamuel Ortiz } 1381853b350SSamuel Ortiz 139733e636fSSebastien Boeuf #[allow(clippy::type_complexity)] resolve(&self, addr: u64) -> Option<(u64, u64, Arc<dyn BusDeviceSync>)>140954f3dd0SYuanchu Xie fn resolve(&self, addr: u64) -> Option<(u64, u64, Arc<dyn BusDeviceSync>)> { 14133796c4bSSamuel Ortiz if let Some((range, dev)) = self.first_before(addr) { 14233796c4bSSamuel Ortiz let offset = addr - range.base; 14333796c4bSSamuel Ortiz if offset < range.len { 14442e54580SSamuel Ortiz return Some((range.base, offset, dev)); 1451853b350SSamuel Ortiz } 1461853b350SSamuel Ortiz } 1471853b350SSamuel Ortiz None 1481853b350SSamuel Ortiz } 1491853b350SSamuel Ortiz insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()>150954f3dd0SYuanchu Xie pub fn insert(&self, device: Arc<dyn BusDeviceSync>, base: u64, len: u64) -> Result<()> { 1511853b350SSamuel Ortiz if len == 0 { 152733e636fSSebastien Boeuf return Err(Error::ZeroSizedRange); 1531853b350SSamuel Ortiz } 1541853b350SSamuel Ortiz 15533796c4bSSamuel Ortiz // Reject all cases where the new device's range overlaps with an existing device. 15633796c4bSSamuel Ortiz if self 15733796c4bSSamuel Ortiz .devices 1581870eb42SSebastien Boeuf .read() 1591870eb42SSebastien Boeuf .unwrap() 16033796c4bSSamuel Ortiz .iter() 16133796c4bSSamuel Ortiz .any(|(range, _dev)| range.overlaps(base, len)) 16233796c4bSSamuel Ortiz { 1631853b350SSamuel Ortiz return Err(Error::Overlap); 1641853b350SSamuel Ortiz } 1651853b350SSamuel Ortiz 16633796c4bSSamuel Ortiz if self 16733796c4bSSamuel Ortiz .devices 1681870eb42SSebastien Boeuf .write() 1691870eb42SSebastien Boeuf .unwrap() 170ca426cfdSSebastien Boeuf .insert(BusRange { base, len }, Arc::downgrade(&device)) 17133796c4bSSamuel Ortiz .is_some() 17233796c4bSSamuel Ortiz { 1731853b350SSamuel Ortiz return Err(Error::Overlap); 1741853b350SSamuel Ortiz } 1751853b350SSamuel Ortiz 1761853b350SSamuel Ortiz Ok(()) 1771853b350SSamuel Ortiz } 1781853b350SSamuel Ortiz 179733e636fSSebastien Boeuf /// Removes the device at the given address space range. remove(&self, base: u64, len: u64) -> Result<()>1801870eb42SSebastien Boeuf pub fn remove(&self, base: u64, len: u64) -> Result<()> { 181733e636fSSebastien Boeuf if len == 0 { 182733e636fSSebastien Boeuf return Err(Error::ZeroSizedRange); 183733e636fSSebastien Boeuf } 184733e636fSSebastien Boeuf 185733e636fSSebastien Boeuf let bus_range = BusRange { base, len }; 186733e636fSSebastien Boeuf 1871870eb42SSebastien Boeuf if self.devices.write().unwrap().remove(&bus_range).is_none() { 188733e636fSSebastien Boeuf return Err(Error::MissingAddressRange); 189733e636fSSebastien Boeuf } 190733e636fSSebastien Boeuf 191733e636fSSebastien Boeuf Ok(()) 192733e636fSSebastien Boeuf } 193733e636fSSebastien Boeuf 1940e21c32cSSebastien Boeuf /// Removes all entries referencing the given device. remove_by_device(&self, device: &Arc<dyn BusDeviceSync>) -> Result<()>195954f3dd0SYuanchu Xie pub fn remove_by_device(&self, device: &Arc<dyn BusDeviceSync>) -> Result<()> { 1960e21c32cSSebastien Boeuf let mut device_list = self.devices.write().unwrap(); 1970e21c32cSSebastien Boeuf let mut remove_key_list = Vec::new(); 1980e21c32cSSebastien Boeuf 1990e21c32cSSebastien Boeuf for (key, value) in device_list.iter() { 2000e21c32cSSebastien Boeuf if Arc::ptr_eq(&value.upgrade().unwrap(), device) { 2010e21c32cSSebastien Boeuf remove_key_list.push(*key); 2020e21c32cSSebastien Boeuf } 2030e21c32cSSebastien Boeuf } 2040e21c32cSSebastien Boeuf 2050e21c32cSSebastien Boeuf for key in remove_key_list.iter() { 2060e21c32cSSebastien Boeuf device_list.remove(key); 2070e21c32cSSebastien Boeuf } 2080e21c32cSSebastien Boeuf 2090e21c32cSSebastien Boeuf Ok(()) 2100e21c32cSSebastien Boeuf } 2110e21c32cSSebastien Boeuf 212733e636fSSebastien Boeuf /// Updates the address range for an existing device. update_range( &self, old_base: u64, old_len: u64, new_base: u64, new_len: u64, ) -> Result<()>213733e636fSSebastien Boeuf pub fn update_range( 2141870eb42SSebastien Boeuf &self, 215733e636fSSebastien Boeuf old_base: u64, 216733e636fSSebastien Boeuf old_len: u64, 217733e636fSSebastien Boeuf new_base: u64, 218733e636fSSebastien Boeuf new_len: u64, 219733e636fSSebastien Boeuf ) -> Result<()> { 220733e636fSSebastien Boeuf // Retrieve the device corresponding to the range 221733e636fSSebastien Boeuf let device = if let Some((_, _, dev)) = self.resolve(old_base) { 222733e636fSSebastien Boeuf dev.clone() 223733e636fSSebastien Boeuf } else { 224733e636fSSebastien Boeuf return Err(Error::MissingAddressRange); 225733e636fSSebastien Boeuf }; 226733e636fSSebastien Boeuf 227733e636fSSebastien Boeuf // Remove the old address range 228733e636fSSebastien Boeuf self.remove(old_base, old_len)?; 229733e636fSSebastien Boeuf 230733e636fSSebastien Boeuf // Insert the new address range 231733e636fSSebastien Boeuf self.insert(device, new_base, new_len) 232733e636fSSebastien Boeuf } 233733e636fSSebastien Boeuf 2341853b350SSamuel Ortiz /// Reads data from the device that owns the range containing `addr` and puts it into `data`. 2351853b350SSamuel Ortiz /// 2361853b350SSamuel Ortiz /// Returns true on success, otherwise `data` is untouched. read(&self, addr: u64, data: &mut [u8]) -> Result<()>237e5ce6dc4SSamuel Ortiz pub fn read(&self, addr: u64, data: &mut [u8]) -> Result<()> { 2388173e1ccSSamuel Ortiz if let Some((base, offset, dev)) = self.resolve(addr) { 2391853b350SSamuel Ortiz // OK to unwrap as lock() failing is a serious error condition and should panic. 240954f3dd0SYuanchu Xie dev.read(base, offset, data); 241e5ce6dc4SSamuel Ortiz Ok(()) 2421853b350SSamuel Ortiz } else { 243e5ce6dc4SSamuel Ortiz Err(Error::MissingAddressRange) 2441853b350SSamuel Ortiz } 2451853b350SSamuel Ortiz } 2461853b350SSamuel Ortiz 2471853b350SSamuel Ortiz /// Writes `data` to the device that owns the range containing `addr`. 2481853b350SSamuel Ortiz /// 2491853b350SSamuel Ortiz /// Returns true on success, otherwise `data` is untouched. write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>>250a8643dc5SRob Bradford pub fn write(&self, addr: u64, data: &[u8]) -> Result<Option<Arc<Barrier>>> { 2518173e1ccSSamuel Ortiz if let Some((base, offset, dev)) = self.resolve(addr) { 2521853b350SSamuel Ortiz // OK to unwrap as lock() failing is a serious error condition and should panic. 253954f3dd0SYuanchu Xie Ok(dev.write(base, offset, data)) 2541853b350SSamuel Ortiz } else { 255e5ce6dc4SSamuel Ortiz Err(Error::MissingAddressRange) 2561853b350SSamuel Ortiz } 2571853b350SSamuel Ortiz } 2581853b350SSamuel Ortiz } 2591853b350SSamuel Ortiz 2601853b350SSamuel Ortiz #[cfg(test)] 2611853b350SSamuel Ortiz mod tests { 2621853b350SSamuel Ortiz use super::*; 2631853b350SSamuel Ortiz 2641853b350SSamuel Ortiz struct DummyDevice; 265954f3dd0SYuanchu Xie impl BusDeviceSync for DummyDevice {} 2661853b350SSamuel Ortiz 2671853b350SSamuel Ortiz struct ConstantDevice; 268954f3dd0SYuanchu Xie impl BusDeviceSync for ConstantDevice { read(&self, _base: u64, offset: u64, data: &mut [u8])269954f3dd0SYuanchu Xie fn read(&self, _base: u64, offset: u64, data: &mut [u8]) { 2701853b350SSamuel Ortiz for (i, v) in data.iter_mut().enumerate() { 2711853b350SSamuel Ortiz *v = (offset as u8) + (i as u8); 2721853b350SSamuel Ortiz } 2731853b350SSamuel Ortiz } 2741853b350SSamuel Ortiz write(&self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>>275954f3dd0SYuanchu Xie fn write(&self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 2761853b350SSamuel Ortiz for (i, v) in data.iter().enumerate() { 2771853b350SSamuel Ortiz assert_eq!(*v, (offset as u8) + (i as u8)) 2781853b350SSamuel Ortiz } 2791fc6d50fSRob Bradford 2801fc6d50fSRob Bradford None 2811853b350SSamuel Ortiz } 2821853b350SSamuel Ortiz } 2831853b350SSamuel Ortiz 2841853b350SSamuel Ortiz #[test] bus_insert()2851853b350SSamuel Ortiz fn bus_insert() { 2861870eb42SSebastien Boeuf let bus = Bus::new(); 287954f3dd0SYuanchu Xie let dummy = Arc::new(DummyDevice); 288297236a7SRuoqing He bus.insert(dummy.clone(), 0x10, 0).unwrap_err(); 289297236a7SRuoqing He bus.insert(dummy.clone(), 0x10, 0x10).unwrap(); 2901853b350SSamuel Ortiz 2911853b350SSamuel Ortiz let result = bus.insert(dummy.clone(), 0x0f, 0x10); 2925e527294SRob Bradford assert_eq!(format!("{result:?}"), "Err(Overlap)"); 2931853b350SSamuel Ortiz 294297236a7SRuoqing He bus.insert(dummy.clone(), 0x10, 0x10).unwrap_err(); 295297236a7SRuoqing He bus.insert(dummy.clone(), 0x10, 0x15).unwrap_err(); 296297236a7SRuoqing He bus.insert(dummy.clone(), 0x12, 0x15).unwrap_err(); 297297236a7SRuoqing He bus.insert(dummy.clone(), 0x12, 0x01).unwrap_err(); 298297236a7SRuoqing He bus.insert(dummy.clone(), 0x0, 0x20).unwrap_err(); 299297236a7SRuoqing He bus.insert(dummy.clone(), 0x20, 0x05).unwrap(); 300297236a7SRuoqing He bus.insert(dummy.clone(), 0x25, 0x05).unwrap(); 301297236a7SRuoqing He bus.insert(dummy, 0x0, 0x10).unwrap(); 3021853b350SSamuel Ortiz } 3031853b350SSamuel Ortiz 3041853b350SSamuel Ortiz #[test] 30574fe0328SRob Bradford #[allow(clippy::redundant_clone)] bus_read_write()3061853b350SSamuel Ortiz fn bus_read_write() { 3071870eb42SSebastien Boeuf let bus = Bus::new(); 308954f3dd0SYuanchu Xie let dummy = Arc::new(DummyDevice); 309297236a7SRuoqing He bus.insert(dummy.clone(), 0x10, 0x10).unwrap(); 310297236a7SRuoqing He bus.read(0x10, &mut [0, 0, 0, 0]).unwrap(); 311297236a7SRuoqing He bus.write(0x10, &[0, 0, 0, 0]).unwrap(); 312297236a7SRuoqing He bus.read(0x11, &mut [0, 0, 0, 0]).unwrap(); 313297236a7SRuoqing He bus.write(0x11, &[0, 0, 0, 0]).unwrap(); 314297236a7SRuoqing He bus.read(0x16, &mut [0, 0, 0, 0]).unwrap(); 315297236a7SRuoqing He bus.write(0x16, &[0, 0, 0, 0]).unwrap(); 316297236a7SRuoqing He bus.read(0x20, &mut [0, 0, 0, 0]).unwrap_err(); 317297236a7SRuoqing He bus.write(0x20, &[0, 0, 0, 0]).unwrap_err(); 318297236a7SRuoqing He bus.read(0x06, &mut [0, 0, 0, 0]).unwrap_err(); 319297236a7SRuoqing He bus.write(0x06, &[0, 0, 0, 0]).unwrap_err(); 3201853b350SSamuel Ortiz } 3211853b350SSamuel Ortiz 3221853b350SSamuel Ortiz #[test] 32374fe0328SRob Bradford #[allow(clippy::redundant_clone)] bus_read_write_values()3241853b350SSamuel Ortiz fn bus_read_write_values() { 3251870eb42SSebastien Boeuf let bus = Bus::new(); 326954f3dd0SYuanchu Xie let dummy = Arc::new(ConstantDevice); 327297236a7SRuoqing He bus.insert(dummy.clone(), 0x10, 0x10).unwrap(); 3281853b350SSamuel Ortiz 3291853b350SSamuel Ortiz let mut values = [0, 1, 2, 3]; 330297236a7SRuoqing He bus.read(0x10, &mut values).unwrap(); 3311853b350SSamuel Ortiz assert_eq!(values, [0, 1, 2, 3]); 332297236a7SRuoqing He bus.write(0x10, &values).unwrap(); 333297236a7SRuoqing He bus.read(0x15, &mut values).unwrap(); 3341853b350SSamuel Ortiz assert_eq!(values, [5, 6, 7, 8]); 335297236a7SRuoqing He bus.write(0x15, &values).unwrap(); 3361853b350SSamuel Ortiz } 3371853b350SSamuel Ortiz 3381853b350SSamuel Ortiz #[test] 33974fe0328SRob Bradford #[allow(clippy::redundant_clone)] busrange_cmp()3401870eb42SSebastien Boeuf fn busrange_cmp() { 34133796c4bSSamuel Ortiz let range = BusRange { base: 0x10, len: 2 }; 34233796c4bSSamuel Ortiz assert_eq!(range, BusRange { base: 0x10, len: 3 }); 34333796c4bSSamuel Ortiz assert_eq!(range, BusRange { base: 0x10, len: 2 }); 3441853b350SSamuel Ortiz 34533796c4bSSamuel Ortiz assert!(range < BusRange { base: 0x12, len: 1 }); 34633796c4bSSamuel Ortiz assert!(range < BusRange { base: 0x12, len: 3 }); 3471853b350SSamuel Ortiz 34833796c4bSSamuel Ortiz assert_eq!(range, range.clone()); 3491853b350SSamuel Ortiz 3501870eb42SSebastien Boeuf let bus = Bus::new(); 3511853b350SSamuel Ortiz let mut data = [1, 2, 3, 4]; 352954f3dd0SYuanchu Xie let device = Arc::new(DummyDevice); 353297236a7SRuoqing He bus.insert(device.clone(), 0x10, 0x10).unwrap(); 354297236a7SRuoqing He bus.write(0x10, &data).unwrap(); 355297236a7SRuoqing He bus.read(0x10, &mut data).unwrap(); 3561853b350SSamuel Ortiz assert_eq!(data, [1, 2, 3, 4]); 3571853b350SSamuel Ortiz } 35833796c4bSSamuel Ortiz 35933796c4bSSamuel Ortiz #[test] bus_range_overlap()36033796c4bSSamuel Ortiz fn bus_range_overlap() { 36133796c4bSSamuel Ortiz let a = BusRange { 36233796c4bSSamuel Ortiz base: 0x1000, 36333796c4bSSamuel Ortiz len: 0x400, 36433796c4bSSamuel Ortiz }; 36533796c4bSSamuel Ortiz assert!(a.overlaps(0x1000, 0x400)); 36633796c4bSSamuel Ortiz assert!(a.overlaps(0xf00, 0x400)); 36733796c4bSSamuel Ortiz assert!(a.overlaps(0x1000, 0x01)); 36833796c4bSSamuel Ortiz assert!(a.overlaps(0xfff, 0x02)); 36933796c4bSSamuel Ortiz assert!(a.overlaps(0x1100, 0x100)); 37033796c4bSSamuel Ortiz assert!(a.overlaps(0x13ff, 0x100)); 37133796c4bSSamuel Ortiz assert!(!a.overlaps(0x1400, 0x100)); 37233796c4bSSamuel Ortiz assert!(!a.overlaps(0xf00, 0x100)); 37333796c4bSSamuel Ortiz } 3741853b350SSamuel Ortiz } 375