|
@@ -295,92 +295,13 @@ impl AmlValue {
|
|
|
/// depending on the size of the field.
|
|
|
pub fn read_field(&self, context: &AmlContext) -> Result<AmlValue, AmlError> {
|
|
|
if let AmlValue::Field { region, flags, offset, length } = self {
|
|
|
- let (region_space, region_base, region_length, parent_device) = {
|
|
|
- if let AmlValue::OpRegion { region, offset, length, parent_device } =
|
|
|
- context.namespace.get(*region)?
|
|
|
- {
|
|
|
- (region, offset, length, parent_device)
|
|
|
- } else {
|
|
|
- return Err(AmlError::FieldRegionIsNotOpRegion);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- match region_space {
|
|
|
- RegionSpace::SystemMemory => {
|
|
|
- let address = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
|
|
|
- match length {
|
|
|
- 8 => Ok(AmlValue::Integer(context.handler.read_u8(address) as u64)),
|
|
|
- 16 => Ok(AmlValue::Integer(context.handler.read_u16(address) as u64)),
|
|
|
- 32 => Ok(AmlValue::Integer(context.handler.read_u32(address) as u64)),
|
|
|
- 64 => Ok(AmlValue::Integer(context.handler.read_u64(address))),
|
|
|
- _ => Err(AmlError::FieldInvalidAccessSize),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- RegionSpace::SystemIo => {
|
|
|
- let port = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
|
|
|
- match length {
|
|
|
- 8 => Ok(AmlValue::Integer(context.handler.read_io_u8(port) as u64)),
|
|
|
- 16 => Ok(AmlValue::Integer(context.handler.read_io_u16(port) as u64)),
|
|
|
- 32 => Ok(AmlValue::Integer(context.handler.read_io_u32(port) as u64)),
|
|
|
- _ => Err(AmlError::FieldInvalidAccessSize),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- RegionSpace::PciConfig => {
|
|
|
- /*
|
|
|
- * First, we need to get some extra information out of objects in the parent object. Both
|
|
|
- * `_SEG` and `_BBN` seem optional, with defaults that line up with legacy PCI implementations
|
|
|
- * (e.g. systems with a single segment group and a single root, respectively).
|
|
|
- */
|
|
|
- let parent_device = parent_device.as_ref().unwrap();
|
|
|
- let seg = match context.namespace.search(&AmlName::from_str("_SEG").unwrap(), parent_device) {
|
|
|
- Ok((_, handle)) => context
|
|
|
- .namespace
|
|
|
- .get(handle)?
|
|
|
- .as_integer(context)?
|
|
|
- .try_into()
|
|
|
- .map_err(|_| AmlError::FieldInvalidAddress)?,
|
|
|
- Err(AmlError::ValueDoesNotExist(_)) => 0,
|
|
|
- Err(err) => return Err(err),
|
|
|
- };
|
|
|
- let bbn = match context.namespace.search(&AmlName::from_str("_BBN").unwrap(), parent_device) {
|
|
|
- Ok((_, handle)) => context
|
|
|
- .namespace
|
|
|
- .get(handle)?
|
|
|
- .as_integer(context)?
|
|
|
- .try_into()
|
|
|
- .map_err(|_| AmlError::FieldInvalidAddress)?,
|
|
|
- Err(AmlError::ValueDoesNotExist(_)) => 0,
|
|
|
- Err(err) => return Err(err),
|
|
|
- };
|
|
|
- let adr = {
|
|
|
- let (_, handle) =
|
|
|
- context.namespace.search(&AmlName::from_str("_ADR").unwrap(), parent_device)?;
|
|
|
- context.namespace.get(handle)?.as_integer(context)?
|
|
|
- };
|
|
|
-
|
|
|
- let device = adr.get_bits(16..24) as u8;
|
|
|
- let function = adr.get_bits(0..8) as u8;
|
|
|
- let offset = (region_base + offset).try_into().map_err(|_| AmlError::FieldInvalidAddress)?;
|
|
|
-
|
|
|
- match length {
|
|
|
- 8 => Ok(AmlValue::Integer(
|
|
|
- context.handler.read_pci_u8(seg, bbn, device, function, offset) as u64,
|
|
|
- )),
|
|
|
- 16 => Ok(AmlValue::Integer(
|
|
|
- context.handler.read_pci_u16(seg, bbn, device, function, offset) as u64,
|
|
|
- )),
|
|
|
- 32 => Ok(AmlValue::Integer(
|
|
|
- context.handler.read_pci_u32(seg, bbn, device, function, offset) as u64,
|
|
|
- )),
|
|
|
- _ => Err(AmlError::FieldInvalidAccessSize),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // TODO
|
|
|
- _ => unimplemented!(),
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * TODO: we need to decide properly how to read from the region itself. Complications:
|
|
|
+ * - if the region has a minimum access size greater than the desired length, we need to read the
|
|
|
+ * minimum and mask it (reading a byte from a WordAcc region)
|
|
|
+ * - if the desired length is larger than we can read, we need to do multiple reads
|
|
|
+ */
|
|
|
+ Ok(AmlValue::Integer(context.read_region(*region, *offset, *length)?))
|
|
|
} else {
|
|
|
Err(AmlError::IncompatibleValueConversion)
|
|
|
}
|