diff --git a/Kernel/Core/device_manager.rs b/Kernel/Core/device_manager.rs
index ecc3b8248c1d81f782a947662f1ba0be7fa24ca0..7bcc173794dfdf3c314467e3b74f84ab7c685fe2 100644
--- a/Kernel/Core/device_manager.rs
+++ b/Kernel/Core/device_manager.rs
@@ -69,13 +69,22 @@ pub trait BusDevice:
 	/// Returns the device's address on the parent bus
 	fn addr(&self) -> u32;
 	/// Returns the specified attribute (or 0, if invalid)
-	fn get_attr(&self, name: &str) -> AttrValue;
+	fn get_attr(&self, name: &str) -> AttrValue {
+		self.get_attr_idx(name, 0)
+	}
+	fn get_attr_idx(&self, name: &str, idx: usize) -> AttrValue;
 	/// Set the specified attribute
-	fn set_attr(&mut self, name: &str, value: AttrValue);
+	fn set_attr(&mut self, name: &str, value: AttrValue) {
+		self.set_attr_idx(name, 0, value)
+	}
+	fn set_attr_idx(&mut self, name: &str, idx: usize, value: AttrValue);
 	/// Set the power state of this device
 	fn set_power(&mut self, state: bool);	// TODO: Power state enum for Off,Standby,Low,On
 	/// Bind to the specified IO block (meaning of `block_id` depends on the bus)
-	fn bind_io(&mut self, block_id: usize) -> IOBinding;
+	fn bind_io(&mut self, block_id: usize) -> IOBinding {
+		self.bind_io_slice(block_id, None)
+	}
+	fn bind_io_slice(&mut self, block_id: usize, slice: Option<(usize,usize)>) -> IOBinding;
 	/// Obtain the specified interrupt vector
 	fn get_irq(&mut self, idx: usize) -> u32;
 }
diff --git a/Kernel/Core/hw/bus_pci.rs b/Kernel/Core/hw/bus_pci.rs
index e4e849cb0f18f1ae6c56e9c0617ded2e75ef9049..3b22891692fbebc437ab92fb9720732612eb97e0 100644
--- a/Kernel/Core/hw/bus_pci.rs
+++ b/Kernel/Core/hw/bus_pci.rs
@@ -95,7 +95,7 @@ impl ::device_manager::BusDevice for PCIDev
 	fn addr(&self) -> u32 {
 		self.addr as u32
 	}
-	fn get_attr(&self, name: &str) -> ::device_manager::AttrValue {
+	fn get_attr_idx(&self, name: &str, idx: usize) -> ::device_manager::AttrValue {
 		use device_manager::AttrValue;
 		match name
 		{
@@ -103,13 +103,21 @@ impl ::device_manager::BusDevice for PCIDev
 		"device" => AttrValue::U32(self.device as u32),
 		"class" => AttrValue::U32(self.class),
 		"bus_master" => AttrValue::U32(if self.config[1] & 4 == 0 { 0 } else { 1 }),
+		"raw_config" => {
+			if idx >= 256 || idx % 4 != 0 {
+				AttrValue::None
+			}
+			else {
+				AttrValue::U32(read_word(self.addr, idx as u8 / 4))
+			}
+			},
 		_ => {
 			log_warning!("Request for non-existant attr '{}' on device 0x{:05x}", name, self.addr);
 			AttrValue::None
 			},
 		}
 	}
-	fn set_attr(&mut self, name: &str, value: ::device_manager::AttrValue) {
+	fn set_attr_idx(&mut self, name: &str, _idx: usize, value: ::device_manager::AttrValue) {
 		use device_manager::AttrValue;
 		match (name,value)
 		{
@@ -138,7 +146,7 @@ impl ::device_manager::BusDevice for PCIDev
 		// Nope
 		todo!("Set power state of PCI devices (state={})", state);
 	}
-	fn bind_io(&mut self, block_id: usize) -> ::device_manager::IOBinding
+	fn bind_io_slice(&mut self, block_id: usize, slice: Option<(usize,usize)>) -> ::device_manager::IOBinding
 	{
 		if block_id > 6 {
 			panic!("PCI bind_io - block_id out of range (max 5, got {})", block_id);
@@ -155,8 +163,29 @@ impl ::device_manager::BusDevice for PCIDev
 			log_error!("PCI bind_io - Request for BAR{} of {:#x} which isn't populated", block_id, self.addr);
 			::device_manager::IOBinding::IO(0,0)
 			},
-		BAR::IO(b,s) => ::device_manager::IOBinding::IO(b,s),
+		BAR::IO(b,s) => {
+			if let Some(slice) = slice {
+				if slice.0 >= s as usize || slice.1 + slice.0 > s as usize {
+					::device_manager::IOBinding::IO(0,0)
+				}
+				else {
+					::device_manager::IOBinding::IO(b + slice.0 as u16, slice.1 as u16)
+				}
+			}
+			else {
+				::device_manager::IOBinding::IO(b,s)
+			}
+			},
 		BAR::Mem(base, size, _prefetchable) => {
+			let (base, size) = if let Some(slice) = slice {
+					if slice.0 >= size as usize || slice.1 + slice.0 > size as usize {
+						return ::device_manager::IOBinding::IO(0,0);
+					}
+					(base + slice.0 as u64, slice.1 as u32)
+				}
+				else {
+					(base, size)
+				};
 			// TODO: Ensure safety by preventing multiple bindings to a BAR
 			// Assume SAFE: Shouldn't be aliased
 			let ah = unsafe {::memory::virt::map_mmio(base as ::memory::PAddr, size as usize).unwrap() };