acpi-rs: add connect_op_regions() + repair initialize_namespace
Add public connect_op_regions() (ACPICA evrgnini.c): \_SB._REG(space, 1) per installed handler space plus <device>._REG(space, 1) per device holding an OpRegion of that space. initialize_namespace() now delegates to it and its ACPICA-order opening (_INI, _SB._INI) is restored after0c11c2b5captured a broken intermediate edit. Completes the _REG wiring begun inc3a27717(which delivered the acpid-side call).
This commit is contained in:
@@ -241,10 +241,79 @@ where
|
|||||||
handlers.insert(space, handler);
|
handlers.insert(space, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `_REG` opregion connect (ACPICA evrgnini.c): `\_SB._REG(space, 1)` per
|
||||||
|
/// installed handler + `<device>._REG(space, 1)` per device holding an
|
||||||
|
/// OpRegion of that space. Firmware gates EC access behind this. Idempotent.
|
||||||
|
pub fn connect_op_regions(&self) {
|
||||||
|
let installed_spaces: Vec<RegionSpace> =
|
||||||
|
self.region_handlers.lock().keys().copied().collect();
|
||||||
|
|
||||||
|
for space in &installed_spaces {
|
||||||
|
let space_id = u8::from(*space) as u64;
|
||||||
|
if let Err(err) = self.evaluate_if_present(
|
||||||
|
AmlName::from_str("\\_SB._REG").unwrap(),
|
||||||
|
vec![Object::Integer(space_id).wrap(), Object::Integer(1).wrap()],
|
||||||
|
) {
|
||||||
|
warn!("\\_SB._REG({:?}, connect) failed: {:?}", space, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut reg_namespace = self.namespace.lock().clone();
|
||||||
|
let _ = reg_namespace.traverse(|path, level| {
|
||||||
|
match level.kind {
|
||||||
|
NamespaceLevelKind::Device
|
||||||
|
| NamespaceLevelKind::Processor
|
||||||
|
| NamespaceLevelKind::ThermalZone
|
||||||
|
| NamespaceLevelKind::PowerResource => {
|
||||||
|
let mut device_spaces: Vec<RegionSpace> = level
|
||||||
|
.values
|
||||||
|
.values()
|
||||||
|
.filter_map(|(_, obj)| match &**obj {
|
||||||
|
Object::OpRegion(region)
|
||||||
|
if installed_spaces.contains(®ion.space) =>
|
||||||
|
{
|
||||||
|
Some(region.space)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
device_spaces.sort();
|
||||||
|
device_spaces.dedup();
|
||||||
|
for space in device_spaces {
|
||||||
|
let space_id = u8::from(space) as u64;
|
||||||
|
if let Ok(reg_path) =
|
||||||
|
AmlName::from_str("_REG").unwrap().resolve(path)
|
||||||
|
{
|
||||||
|
let _ = self.evaluate_if_present(
|
||||||
|
reg_path,
|
||||||
|
vec![Object::Integer(space_id).wrap(), Object::Integer(1).wrap()],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
_ => Ok(true),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Initialize the namespace - this should be called after all tables have been loaded and
|
/// Initialize the namespace - this should be called after all tables have been loaded and
|
||||||
/// operation region handlers registered. Specifically, it will call relevant `_STA`, `_INI`,
|
/// operation region handlers registered. Specifically, it will call relevant `_STA`, `_INI`,
|
||||||
/// and `_REG` methods.
|
/// and `_REG` methods.
|
||||||
pub fn initialize_namespace(&self) {
|
pub fn initialize_namespace(&self) {
|
||||||
|
/*
|
||||||
|
* This should match the initialization order of ACPICA and uACPI.
|
||||||
|
*/
|
||||||
|
if let Err(err) = self.evaluate_if_present(AmlName::from_str("\\_INI").unwrap(), vec![]) {
|
||||||
|
warn!("Invoking \\_INI failed: {:?}", err);
|
||||||
|
}
|
||||||
|
if let Err(err) = self.evaluate_if_present(AmlName::from_str("\\_SB._INI").unwrap(), vec![]) {
|
||||||
|
warn!("Invoking \\_SB._INI failed: {:?}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.connect_op_regions();
|
||||||
|
|
||||||
|
/*
|
||||||
* We can now initialize each device in the namespace. For each device, we evaluate `_STA`,
|
* We can now initialize each device in the namespace. For each device, we evaluate `_STA`,
|
||||||
* which indicates if the device is present and functional. If this method does not exist,
|
* which indicates if the device is present and functional. If this method does not exist,
|
||||||
* we assume the device should be initialized.
|
* we assume the device should be initialized.
|
||||||
|
|||||||
Reference in New Issue
Block a user