1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::str::FromStr;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
9*bb4ee6a4SAndroid Build Coastguard Worker
10*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml;
11*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml::Aml;
12*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::bail;
13*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::custom_serde::serialize_arc_mutex;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Error as SysError;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::EventWaitResult;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
26*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
27*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
28*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
29*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
30*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::GpeNotify;
31*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::PmResource;
32*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::PmeNotify;
33*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmRequest;
34*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmResponse;
35*bb4ee6a4SAndroid Build Coastguard Worker
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::ac_adapter::AcAdapter;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pm::PmConfig;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusResumeDevice;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
45*bb4ee6a4SAndroid Build Coastguard Worker
46*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
47*bb4ee6a4SAndroid Build Coastguard Worker pub enum ACPIPMError {
48*bb4ee6a4SAndroid Build Coastguard Worker /// Creating WaitContext failed.
49*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create wait context: {0}")]
50*bb4ee6a4SAndroid Build Coastguard Worker CreateWaitContext(SysError),
51*bb4ee6a4SAndroid Build Coastguard Worker /// Error while waiting for events.
52*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to wait for events: {0}")]
53*bb4ee6a4SAndroid Build Coastguard Worker WaitError(SysError),
54*bb4ee6a4SAndroid Build Coastguard Worker #[error("Did not find group_id corresponding to acpi_mc_group")]
55*bb4ee6a4SAndroid Build Coastguard Worker AcpiMcGroupError,
56*bb4ee6a4SAndroid Build Coastguard Worker #[error("Failed to create and bind NETLINK_GENERIC socket for acpi_mc_group: {0}")]
57*bb4ee6a4SAndroid Build Coastguard Worker AcpiEventSockError(base::Error),
58*bb4ee6a4SAndroid Build Coastguard Worker #[error("GPE {0} is out of bound")]
59*bb4ee6a4SAndroid Build Coastguard Worker GpeOutOfBound(u32),
60*bb4ee6a4SAndroid Build Coastguard Worker }
61*bb4ee6a4SAndroid Build Coastguard Worker
62*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
63*bb4ee6a4SAndroid Build Coastguard Worker pub enum ACPIPMFixedEvent {
64*bb4ee6a4SAndroid Build Coastguard Worker GlobalLock,
65*bb4ee6a4SAndroid Build Coastguard Worker PowerButton,
66*bb4ee6a4SAndroid Build Coastguard Worker SleepButton,
67*bb4ee6a4SAndroid Build Coastguard Worker RTC,
68*bb4ee6a4SAndroid Build Coastguard Worker }
69*bb4ee6a4SAndroid Build Coastguard Worker
70*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize)]
71*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct Pm1Resource {
72*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) status: u16,
73*bb4ee6a4SAndroid Build Coastguard Worker enable: u16,
74*bb4ee6a4SAndroid Build Coastguard Worker control: u16,
75*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
76*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube: Arc<Mutex<SendTube>>,
77*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
78*bb4ee6a4SAndroid Build Coastguard Worker rtc_clear_evt: Option<Event>,
79*bb4ee6a4SAndroid Build Coastguard Worker }
80*bb4ee6a4SAndroid Build Coastguard Worker
81*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize)]
82*bb4ee6a4SAndroid Build Coastguard Worker struct Pm1ResourceSerializable {
83*bb4ee6a4SAndroid Build Coastguard Worker status: u16,
84*bb4ee6a4SAndroid Build Coastguard Worker enable: u16,
85*bb4ee6a4SAndroid Build Coastguard Worker control: u16,
86*bb4ee6a4SAndroid Build Coastguard Worker }
87*bb4ee6a4SAndroid Build Coastguard Worker
88*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize)]
89*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct GpeResource {
90*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) status: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
91*bb4ee6a4SAndroid Build Coastguard Worker enable: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
92*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
93*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) gpe_notify: BTreeMap<u32, Vec<Arc<Mutex<dyn GpeNotify>>>>,
94*bb4ee6a4SAndroid Build Coastguard Worker // For each triggered GPE, a vector of events to check when resampling
95*bb4ee6a4SAndroid Build Coastguard Worker // sci_evt. If any events are un-signaled, then sci_evt should be re-asserted.
96*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
97*bb4ee6a4SAndroid Build Coastguard Worker pending_clear_evts: BTreeMap<u32, Vec<Event>>,
98*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
99*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube: Arc<Mutex<SendTube>>,
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker
102*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize)]
103*bb4ee6a4SAndroid Build Coastguard Worker struct GpeResourceSerializable {
104*bb4ee6a4SAndroid Build Coastguard Worker status: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
105*bb4ee6a4SAndroid Build Coastguard Worker enable: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker
108*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Clone)]
109*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct PciResource {
110*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing, skip_deserializing)]
111*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) pme_notify: BTreeMap<u8, Vec<Arc<Mutex<dyn PmeNotify>>>>,
112*bb4ee6a4SAndroid Build Coastguard Worker }
113*bb4ee6a4SAndroid Build Coastguard Worker
114*bb4ee6a4SAndroid Build Coastguard Worker /// ACPI PM resource for handling OS suspend/resume request
115*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
116*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize)]
117*bb4ee6a4SAndroid Build Coastguard Worker pub struct ACPIPMResource {
118*bb4ee6a4SAndroid Build Coastguard Worker // This is SCI interrupt that will be raised in the VM.
119*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
120*bb4ee6a4SAndroid Build Coastguard Worker sci_evt: IrqLevelEvent,
121*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
122*bb4ee6a4SAndroid Build Coastguard Worker worker_thread: Option<WorkerThread<()>>,
123*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
124*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube: Arc<Mutex<SendTube>>,
125*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
126*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: SendTube,
127*bb4ee6a4SAndroid Build Coastguard Worker #[serde(serialize_with = "serialize_arc_mutex")]
128*bb4ee6a4SAndroid Build Coastguard Worker pm1: Arc<Mutex<Pm1Resource>>,
129*bb4ee6a4SAndroid Build Coastguard Worker #[serde(serialize_with = "serialize_arc_mutex")]
130*bb4ee6a4SAndroid Build Coastguard Worker gpe0: Arc<Mutex<GpeResource>>,
131*bb4ee6a4SAndroid Build Coastguard Worker #[serde(serialize_with = "serialize_arc_mutex")]
132*bb4ee6a4SAndroid Build Coastguard Worker pci: Arc<Mutex<PciResource>>,
133*bb4ee6a4SAndroid Build Coastguard Worker #[serde(skip_serializing)]
134*bb4ee6a4SAndroid Build Coastguard Worker acdc: Option<Arc<Mutex<AcAdapter>>>,
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker
137*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize)]
138*bb4ee6a4SAndroid Build Coastguard Worker struct ACPIPMResrourceSerializable {
139*bb4ee6a4SAndroid Build Coastguard Worker pm1: Pm1ResourceSerializable,
140*bb4ee6a4SAndroid Build Coastguard Worker gpe0: GpeResourceSerializable,
141*bb4ee6a4SAndroid Build Coastguard Worker }
142*bb4ee6a4SAndroid Build Coastguard Worker
143*bb4ee6a4SAndroid Build Coastguard Worker impl ACPIPMResource {
144*bb4ee6a4SAndroid Build Coastguard Worker /// Constructs ACPI Power Management Resouce.
145*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
new( sci_evt: IrqLevelEvent, suspend_tube: Arc<Mutex<SendTube>>, exit_evt_wrtube: SendTube, acdc: Option<Arc<Mutex<AcAdapter>>>, ) -> ACPIPMResource146*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(
147*bb4ee6a4SAndroid Build Coastguard Worker sci_evt: IrqLevelEvent,
148*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube: Arc<Mutex<SendTube>>,
149*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: SendTube,
150*bb4ee6a4SAndroid Build Coastguard Worker acdc: Option<Arc<Mutex<AcAdapter>>>,
151*bb4ee6a4SAndroid Build Coastguard Worker ) -> ACPIPMResource {
152*bb4ee6a4SAndroid Build Coastguard Worker let pm1 = Pm1Resource {
153*bb4ee6a4SAndroid Build Coastguard Worker status: 0,
154*bb4ee6a4SAndroid Build Coastguard Worker enable: 0,
155*bb4ee6a4SAndroid Build Coastguard Worker control: 0,
156*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube: suspend_tube.clone(),
157*bb4ee6a4SAndroid Build Coastguard Worker rtc_clear_evt: None,
158*bb4ee6a4SAndroid Build Coastguard Worker };
159*bb4ee6a4SAndroid Build Coastguard Worker let gpe0 = GpeResource {
160*bb4ee6a4SAndroid Build Coastguard Worker status: Default::default(),
161*bb4ee6a4SAndroid Build Coastguard Worker enable: Default::default(),
162*bb4ee6a4SAndroid Build Coastguard Worker gpe_notify: BTreeMap::new(),
163*bb4ee6a4SAndroid Build Coastguard Worker pending_clear_evts: BTreeMap::new(),
164*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube: suspend_tube.clone(),
165*bb4ee6a4SAndroid Build Coastguard Worker };
166*bb4ee6a4SAndroid Build Coastguard Worker let pci = PciResource {
167*bb4ee6a4SAndroid Build Coastguard Worker pme_notify: BTreeMap::new(),
168*bb4ee6a4SAndroid Build Coastguard Worker };
169*bb4ee6a4SAndroid Build Coastguard Worker
170*bb4ee6a4SAndroid Build Coastguard Worker ACPIPMResource {
171*bb4ee6a4SAndroid Build Coastguard Worker sci_evt,
172*bb4ee6a4SAndroid Build Coastguard Worker worker_thread: None,
173*bb4ee6a4SAndroid Build Coastguard Worker suspend_tube,
174*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube,
175*bb4ee6a4SAndroid Build Coastguard Worker pm1: Arc::new(Mutex::new(pm1)),
176*bb4ee6a4SAndroid Build Coastguard Worker gpe0: Arc::new(Mutex::new(gpe0)),
177*bb4ee6a4SAndroid Build Coastguard Worker pci: Arc::new(Mutex::new(pci)),
178*bb4ee6a4SAndroid Build Coastguard Worker acdc,
179*bb4ee6a4SAndroid Build Coastguard Worker }
180*bb4ee6a4SAndroid Build Coastguard Worker }
181*bb4ee6a4SAndroid Build Coastguard Worker
start(&mut self)182*bb4ee6a4SAndroid Build Coastguard Worker pub fn start(&mut self) {
183*bb4ee6a4SAndroid Build Coastguard Worker let sci_evt = self.sci_evt.try_clone().expect("failed to clone event");
184*bb4ee6a4SAndroid Build Coastguard Worker let pm1 = self.pm1.clone();
185*bb4ee6a4SAndroid Build Coastguard Worker let gpe0 = self.gpe0.clone();
186*bb4ee6a4SAndroid Build Coastguard Worker let acdc = self.acdc.clone();
187*bb4ee6a4SAndroid Build Coastguard Worker
188*bb4ee6a4SAndroid Build Coastguard Worker let acpi_event_ignored_gpe = Vec::new();
189*bb4ee6a4SAndroid Build Coastguard Worker
190*bb4ee6a4SAndroid Build Coastguard Worker self.worker_thread = Some(WorkerThread::start("ACPI PM worker", move |kill_evt| {
191*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = run_worker(sci_evt, kill_evt, pm1, gpe0, acpi_event_ignored_gpe, acdc) {
192*bb4ee6a4SAndroid Build Coastguard Worker error!("{}", e);
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker }));
195*bb4ee6a4SAndroid Build Coastguard Worker }
196*bb4ee6a4SAndroid Build Coastguard Worker }
197*bb4ee6a4SAndroid Build Coastguard Worker
198*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for ACPIPMResource {
snapshot(&mut self) -> anyhow::Result<serde_json::Value>199*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
200*bb4ee6a4SAndroid Build Coastguard Worker if !self.gpe0.lock().pending_clear_evts.is_empty() {
201*bb4ee6a4SAndroid Build Coastguard Worker bail!("ACPIPMResource is busy");
202*bb4ee6a4SAndroid Build Coastguard Worker }
203*bb4ee6a4SAndroid Build Coastguard Worker serde_json::to_value(&self)
204*bb4ee6a4SAndroid Build Coastguard Worker .with_context(|| format!("error serializing {}", self.debug_label()))
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>207*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
208*bb4ee6a4SAndroid Build Coastguard Worker let acpi_snapshot: ACPIPMResrourceSerializable = serde_json::from_value(data)
209*bb4ee6a4SAndroid Build Coastguard Worker .with_context(|| format!("error deserializing {}", self.debug_label()))?;
210*bb4ee6a4SAndroid Build Coastguard Worker {
211*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
212*bb4ee6a4SAndroid Build Coastguard Worker pm1.status = acpi_snapshot.pm1.status;
213*bb4ee6a4SAndroid Build Coastguard Worker pm1.enable = acpi_snapshot.pm1.enable;
214*bb4ee6a4SAndroid Build Coastguard Worker pm1.control = acpi_snapshot.pm1.control;
215*bb4ee6a4SAndroid Build Coastguard Worker }
216*bb4ee6a4SAndroid Build Coastguard Worker {
217*bb4ee6a4SAndroid Build Coastguard Worker let mut gpe0 = self.gpe0.lock();
218*bb4ee6a4SAndroid Build Coastguard Worker gpe0.status = acpi_snapshot.gpe0.status;
219*bb4ee6a4SAndroid Build Coastguard Worker gpe0.enable = acpi_snapshot.gpe0.enable;
220*bb4ee6a4SAndroid Build Coastguard Worker }
221*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
222*bb4ee6a4SAndroid Build Coastguard Worker }
223*bb4ee6a4SAndroid Build Coastguard Worker
sleep(&mut self) -> anyhow::Result<()>224*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> {
225*bb4ee6a4SAndroid Build Coastguard Worker if let Some(worker_thread) = self.worker_thread.take() {
226*bb4ee6a4SAndroid Build Coastguard Worker worker_thread.stop();
227*bb4ee6a4SAndroid Build Coastguard Worker }
228*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
229*bb4ee6a4SAndroid Build Coastguard Worker }
230*bb4ee6a4SAndroid Build Coastguard Worker
wake(&mut self) -> anyhow::Result<()>231*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> {
232*bb4ee6a4SAndroid Build Coastguard Worker self.start();
233*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
234*bb4ee6a4SAndroid Build Coastguard Worker }
235*bb4ee6a4SAndroid Build Coastguard Worker }
236*bb4ee6a4SAndroid Build Coastguard Worker
run_worker( sci_evt: IrqLevelEvent, kill_evt: Event, pm1: Arc<Mutex<Pm1Resource>>, gpe0: Arc<Mutex<GpeResource>>, acpi_event_ignored_gpe: Vec<u32>, arced_ac_adapter: Option<Arc<Mutex<AcAdapter>>>, ) -> Result<(), ACPIPMError>237*bb4ee6a4SAndroid Build Coastguard Worker fn run_worker(
238*bb4ee6a4SAndroid Build Coastguard Worker sci_evt: IrqLevelEvent,
239*bb4ee6a4SAndroid Build Coastguard Worker kill_evt: Event,
240*bb4ee6a4SAndroid Build Coastguard Worker pm1: Arc<Mutex<Pm1Resource>>,
241*bb4ee6a4SAndroid Build Coastguard Worker gpe0: Arc<Mutex<GpeResource>>,
242*bb4ee6a4SAndroid Build Coastguard Worker acpi_event_ignored_gpe: Vec<u32>,
243*bb4ee6a4SAndroid Build Coastguard Worker arced_ac_adapter: Option<Arc<Mutex<AcAdapter>>>,
244*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<(), ACPIPMError> {
245*bb4ee6a4SAndroid Build Coastguard Worker let acpi_event_sock = crate::sys::get_acpi_event_sock()?;
246*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken)]
247*bb4ee6a4SAndroid Build Coastguard Worker enum Token {
248*bb4ee6a4SAndroid Build Coastguard Worker AcpiEvent,
249*bb4ee6a4SAndroid Build Coastguard Worker InterruptResample,
250*bb4ee6a4SAndroid Build Coastguard Worker Kill,
251*bb4ee6a4SAndroid Build Coastguard Worker }
252*bb4ee6a4SAndroid Build Coastguard Worker
253*bb4ee6a4SAndroid Build Coastguard Worker let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
254*bb4ee6a4SAndroid Build Coastguard Worker (sci_evt.get_resample(), Token::InterruptResample),
255*bb4ee6a4SAndroid Build Coastguard Worker (&kill_evt, Token::Kill),
256*bb4ee6a4SAndroid Build Coastguard Worker ])
257*bb4ee6a4SAndroid Build Coastguard Worker .map_err(ACPIPMError::CreateWaitContext)?;
258*bb4ee6a4SAndroid Build Coastguard Worker if let Some(acpi_event_sock) = &acpi_event_sock {
259*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx
260*bb4ee6a4SAndroid Build Coastguard Worker .add(acpi_event_sock, Token::AcpiEvent)
261*bb4ee6a4SAndroid Build Coastguard Worker .map_err(ACPIPMError::CreateWaitContext)?;
262*bb4ee6a4SAndroid Build Coastguard Worker }
263*bb4ee6a4SAndroid Build Coastguard Worker
264*bb4ee6a4SAndroid Build Coastguard Worker loop {
265*bb4ee6a4SAndroid Build Coastguard Worker let events = wait_ctx.wait().map_err(ACPIPMError::WaitError)?;
266*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) {
267*bb4ee6a4SAndroid Build Coastguard Worker match event.token {
268*bb4ee6a4SAndroid Build Coastguard Worker Token::AcpiEvent => {
269*bb4ee6a4SAndroid Build Coastguard Worker crate::sys::acpi_event_run(
270*bb4ee6a4SAndroid Build Coastguard Worker &sci_evt,
271*bb4ee6a4SAndroid Build Coastguard Worker &acpi_event_sock,
272*bb4ee6a4SAndroid Build Coastguard Worker &gpe0,
273*bb4ee6a4SAndroid Build Coastguard Worker &acpi_event_ignored_gpe,
274*bb4ee6a4SAndroid Build Coastguard Worker &arced_ac_adapter,
275*bb4ee6a4SAndroid Build Coastguard Worker );
276*bb4ee6a4SAndroid Build Coastguard Worker }
277*bb4ee6a4SAndroid Build Coastguard Worker Token::InterruptResample => {
278*bb4ee6a4SAndroid Build Coastguard Worker sci_evt.clear_resample();
279*bb4ee6a4SAndroid Build Coastguard Worker
280*bb4ee6a4SAndroid Build Coastguard Worker // Re-trigger SCI if PM1 or GPE status is still not cleared.
281*bb4ee6a4SAndroid Build Coastguard Worker pm1.lock().resample_clear_evts_and_trigger(&sci_evt);
282*bb4ee6a4SAndroid Build Coastguard Worker gpe0.lock().resample_clear_evts_and_trigger(&sci_evt);
283*bb4ee6a4SAndroid Build Coastguard Worker }
284*bb4ee6a4SAndroid Build Coastguard Worker Token::Kill => return Ok(()),
285*bb4ee6a4SAndroid Build Coastguard Worker }
286*bb4ee6a4SAndroid Build Coastguard Worker }
287*bb4ee6a4SAndroid Build Coastguard Worker }
288*bb4ee6a4SAndroid Build Coastguard Worker }
289*bb4ee6a4SAndroid Build Coastguard Worker
290*bb4ee6a4SAndroid Build Coastguard Worker impl Pm1Resource {
trigger_sci(&self, sci_evt: &IrqLevelEvent)291*bb4ee6a4SAndroid Build Coastguard Worker fn trigger_sci(&self, sci_evt: &IrqLevelEvent) {
292*bb4ee6a4SAndroid Build Coastguard Worker if self.status & self.enable & ACPIPMFixedEvent::bitmask_all() != 0 {
293*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = sci_evt.trigger() {
294*bb4ee6a4SAndroid Build Coastguard Worker error!("ACPIPM: failed to trigger sci event for pm1: {}", e);
295*bb4ee6a4SAndroid Build Coastguard Worker }
296*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.suspend_tube.lock().send(&false) {
297*bb4ee6a4SAndroid Build Coastguard Worker error!("ACPIPM: failed to trigger wake event: {}", e);
298*bb4ee6a4SAndroid Build Coastguard Worker }
299*bb4ee6a4SAndroid Build Coastguard Worker }
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker
resample_clear_evts_and_trigger(&mut self, sci_evt: &IrqLevelEvent)302*bb4ee6a4SAndroid Build Coastguard Worker fn resample_clear_evts_and_trigger(&mut self, sci_evt: &IrqLevelEvent) {
303*bb4ee6a4SAndroid Build Coastguard Worker if let Some(clear_evt) = self.rtc_clear_evt.take() {
304*bb4ee6a4SAndroid Build Coastguard Worker if clear_evt.wait_timeout(Duration::ZERO) == Ok(EventWaitResult::TimedOut) {
305*bb4ee6a4SAndroid Build Coastguard Worker self.rtc_clear_evt = Some(clear_evt);
306*bb4ee6a4SAndroid Build Coastguard Worker self.status |= ACPIPMFixedEvent::RTC.bitmask();
307*bb4ee6a4SAndroid Build Coastguard Worker }
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker self.trigger_sci(sci_evt);
310*bb4ee6a4SAndroid Build Coastguard Worker }
311*bb4ee6a4SAndroid Build Coastguard Worker }
312*bb4ee6a4SAndroid Build Coastguard Worker
313*bb4ee6a4SAndroid Build Coastguard Worker impl GpeResource {
trigger_sci(&self, sci_evt: &IrqLevelEvent)314*bb4ee6a4SAndroid Build Coastguard Worker pub fn trigger_sci(&self, sci_evt: &IrqLevelEvent) {
315*bb4ee6a4SAndroid Build Coastguard Worker if (0..self.status.len()).any(|i| self.status[i] & self.enable[i] != 0) {
316*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = sci_evt.trigger() {
317*bb4ee6a4SAndroid Build Coastguard Worker error!("ACPIPM: failed to trigger sci event for gpe: {}", e);
318*bb4ee6a4SAndroid Build Coastguard Worker }
319*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.suspend_tube.lock().send(&false) {
320*bb4ee6a4SAndroid Build Coastguard Worker error!("ACPIPM: failed to trigger wake event: {}", e);
321*bb4ee6a4SAndroid Build Coastguard Worker }
322*bb4ee6a4SAndroid Build Coastguard Worker }
323*bb4ee6a4SAndroid Build Coastguard Worker }
324*bb4ee6a4SAndroid Build Coastguard Worker
set_active(&mut self, gpe: u32) -> Result<(), ACPIPMError>325*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_active(&mut self, gpe: u32) -> Result<(), ACPIPMError> {
326*bb4ee6a4SAndroid Build Coastguard Worker if let Some(status_byte) = self.status.get_mut(gpe as usize / 8) {
327*bb4ee6a4SAndroid Build Coastguard Worker *status_byte |= 1 << (gpe % 8);
328*bb4ee6a4SAndroid Build Coastguard Worker } else {
329*bb4ee6a4SAndroid Build Coastguard Worker return Err(ACPIPMError::GpeOutOfBound(gpe));
330*bb4ee6a4SAndroid Build Coastguard Worker }
331*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
332*bb4ee6a4SAndroid Build Coastguard Worker }
333*bb4ee6a4SAndroid Build Coastguard Worker
resample_clear_evts_and_trigger(&mut self, sci_evt: &IrqLevelEvent)334*bb4ee6a4SAndroid Build Coastguard Worker pub fn resample_clear_evts_and_trigger(&mut self, sci_evt: &IrqLevelEvent) {
335*bb4ee6a4SAndroid Build Coastguard Worker let mut retained = Vec::new();
336*bb4ee6a4SAndroid Build Coastguard Worker self.pending_clear_evts.retain(|gpe, clear_evts| {
337*bb4ee6a4SAndroid Build Coastguard Worker clear_evts.retain(|clear_evt| {
338*bb4ee6a4SAndroid Build Coastguard Worker clear_evt.wait_timeout(Duration::ZERO) == Ok(EventWaitResult::TimedOut)
339*bb4ee6a4SAndroid Build Coastguard Worker });
340*bb4ee6a4SAndroid Build Coastguard Worker if !clear_evts.is_empty() {
341*bb4ee6a4SAndroid Build Coastguard Worker retained.push(*gpe);
342*bb4ee6a4SAndroid Build Coastguard Worker }
343*bb4ee6a4SAndroid Build Coastguard Worker !clear_evts.is_empty()
344*bb4ee6a4SAndroid Build Coastguard Worker });
345*bb4ee6a4SAndroid Build Coastguard Worker for gpe in retained.into_iter() {
346*bb4ee6a4SAndroid Build Coastguard Worker self.set_active(gpe).expect("bad gpe index");
347*bb4ee6a4SAndroid Build Coastguard Worker }
348*bb4ee6a4SAndroid Build Coastguard Worker
349*bb4ee6a4SAndroid Build Coastguard Worker self.trigger_sci(sci_evt);
350*bb4ee6a4SAndroid Build Coastguard Worker }
351*bb4ee6a4SAndroid Build Coastguard Worker }
352*bb4ee6a4SAndroid Build Coastguard Worker
353*bb4ee6a4SAndroid Build Coastguard Worker /// the ACPI PM register length.
354*bb4ee6a4SAndroid Build Coastguard Worker pub const ACPIPM_RESOURCE_EVENTBLK_LEN: u8 = 4;
355*bb4ee6a4SAndroid Build Coastguard Worker pub const ACPIPM_RESOURCE_CONTROLBLK_LEN: u8 = 2;
356*bb4ee6a4SAndroid Build Coastguard Worker pub const ACPIPM_RESOURCE_GPE0_BLK_LEN: u8 = 64;
357*bb4ee6a4SAndroid Build Coastguard Worker pub const ACPIPM_RESOURCE_LEN: u8 = ACPIPM_RESOURCE_EVENTBLK_LEN + 4 + ACPIPM_RESOURCE_GPE0_BLK_LEN;
358*bb4ee6a4SAndroid Build Coastguard Worker
359*bb4ee6a4SAndroid Build Coastguard Worker // Should be in sync with gpe_allocator range
360*bb4ee6a4SAndroid Build Coastguard Worker pub const ACPIPM_GPE_MAX: u16 = ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2 * 8 - 1;
361*bb4ee6a4SAndroid Build Coastguard Worker
362*bb4ee6a4SAndroid Build Coastguard Worker /// ACPI PM register value definitions
363*bb4ee6a4SAndroid Build Coastguard Worker
364*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.4.1.1 PM1 Status Registers, ACPI Spec Version 6.4
365*bb4ee6a4SAndroid Build Coastguard Worker /// Register Location: <PM1a_EVT_BLK / PM1b_EVT_BLK> System I/O or Memory Space (defined in FADT)
366*bb4ee6a4SAndroid Build Coastguard Worker /// Size: PM1_EVT_LEN / 2 (defined in FADT)
367*bb4ee6a4SAndroid Build Coastguard Worker const PM1_STATUS: u16 = 0;
368*bb4ee6a4SAndroid Build Coastguard Worker
369*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.4.1.2 PM1Enable Registers, ACPI Spec Version 6.4
370*bb4ee6a4SAndroid Build Coastguard Worker /// Register Location: <<PM1a_EVT_BLK / PM1b_EVT_BLK> + PM1_EVT_LEN / 2 System I/O or Memory Space
371*bb4ee6a4SAndroid Build Coastguard Worker /// (defined in FADT)
372*bb4ee6a4SAndroid Build Coastguard Worker /// Size: PM1_EVT_LEN / 2 (defined in FADT)
373*bb4ee6a4SAndroid Build Coastguard Worker const PM1_ENABLE: u16 = PM1_STATUS + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2);
374*bb4ee6a4SAndroid Build Coastguard Worker
375*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.4.2.1 PM1 Control Registers, ACPI Spec Version 6.4
376*bb4ee6a4SAndroid Build Coastguard Worker /// Register Location: <PM1a_CNT_BLK / PM1b_CNT_BLK> System I/O or Memory Space (defined in FADT)
377*bb4ee6a4SAndroid Build Coastguard Worker /// Size: PM1_CNT_LEN (defined in FADT)
378*bb4ee6a4SAndroid Build Coastguard Worker const PM1_CONTROL: u16 = PM1_STATUS + ACPIPM_RESOURCE_EVENTBLK_LEN as u16;
379*bb4ee6a4SAndroid Build Coastguard Worker
380*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.5.1 General-Purpose Event Register Blocks, ACPI Spec Version 6.4
381*bb4ee6a4SAndroid Build Coastguard Worker /// - Each register block contains two registers: an enable and a status register.
382*bb4ee6a4SAndroid Build Coastguard Worker /// - Each register block is 32-bit aligned.
383*bb4ee6a4SAndroid Build Coastguard Worker /// - Each register in the block is accessed as a byte.
384*bb4ee6a4SAndroid Build Coastguard Worker ///
385*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.5.1.1 General-Purpose Event 0 Register Block, ACPI Spec Version 6.4
386*bb4ee6a4SAndroid Build Coastguard Worker /// This register block consists of two registers: The GPE0_STS and the GPE0_EN registers. Each
387*bb4ee6a4SAndroid Build Coastguard Worker /// register’s length is defined to be half the length of the GPE0 register block, and is described
388*bb4ee6a4SAndroid Build Coastguard Worker /// in the ACPI FADT’s GPE0_BLK and GPE0_BLK_LEN operators.
389*bb4ee6a4SAndroid Build Coastguard Worker ///
390*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.5.1.1.1 General-Purpose Event 0 Status Register, ACPI Spec Version 6.4
391*bb4ee6a4SAndroid Build Coastguard Worker /// Register Location: <GPE0_STS> System I/O or System Memory Space (defined in FADT)
392*bb4ee6a4SAndroid Build Coastguard Worker /// Size: GPE0_BLK_LEN/2 (defined in FADT)
393*bb4ee6a4SAndroid Build Coastguard Worker const GPE0_STATUS: u16 = PM1_STATUS + ACPIPM_RESOURCE_EVENTBLK_LEN as u16 + 4; // ensure alignment
394*bb4ee6a4SAndroid Build Coastguard Worker
395*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.5.1.1.2 General-Purpose Event 0 Enable Register, ACPI Spec Version 6.4
396*bb4ee6a4SAndroid Build Coastguard Worker /// Register Location: <GPE0_EN> System I/O or System Memory Space (defined in FADT)
397*bb4ee6a4SAndroid Build Coastguard Worker /// Size: GPE0_BLK_LEN/2 (defined in FADT)
398*bb4ee6a4SAndroid Build Coastguard Worker const GPE0_ENABLE: u16 = GPE0_STATUS + (ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2);
399*bb4ee6a4SAndroid Build Coastguard Worker
400*bb4ee6a4SAndroid Build Coastguard Worker /// Section 4.8.4.1.1, 4.8.4.1.2 Fixed event bits in both PM1 Status and PM1 Enable registers.
401*bb4ee6a4SAndroid Build Coastguard Worker const BITSHIFT_PM1_GBL: u16 = 5;
402*bb4ee6a4SAndroid Build Coastguard Worker const BITSHIFT_PM1_PWRBTN: u16 = 8;
403*bb4ee6a4SAndroid Build Coastguard Worker const BITSHIFT_PM1_SLPBTN: u16 = 9;
404*bb4ee6a4SAndroid Build Coastguard Worker const BITSHIFT_PM1_RTC: u16 = 10;
405*bb4ee6a4SAndroid Build Coastguard Worker
406*bb4ee6a4SAndroid Build Coastguard Worker const BITMASK_PM1CNT_SLEEP_ENABLE: u16 = 0x2000;
407*bb4ee6a4SAndroid Build Coastguard Worker const BITMASK_PM1CNT_WAKE_STATUS: u16 = 0x8000;
408*bb4ee6a4SAndroid Build Coastguard Worker
409*bb4ee6a4SAndroid Build Coastguard Worker const BITMASK_PM1CNT_SLEEP_TYPE: u16 = 0x1C00;
410*bb4ee6a4SAndroid Build Coastguard Worker const SLEEP_TYPE_S1: u16 = 1 << 10;
411*bb4ee6a4SAndroid Build Coastguard Worker const SLEEP_TYPE_S5: u16 = 0 << 10;
412*bb4ee6a4SAndroid Build Coastguard Worker
413*bb4ee6a4SAndroid Build Coastguard Worker impl ACPIPMFixedEvent {
bitshift(self) -> u16414*bb4ee6a4SAndroid Build Coastguard Worker fn bitshift(self) -> u16 {
415*bb4ee6a4SAndroid Build Coastguard Worker match self {
416*bb4ee6a4SAndroid Build Coastguard Worker ACPIPMFixedEvent::GlobalLock => BITSHIFT_PM1_GBL,
417*bb4ee6a4SAndroid Build Coastguard Worker ACPIPMFixedEvent::PowerButton => BITSHIFT_PM1_PWRBTN,
418*bb4ee6a4SAndroid Build Coastguard Worker ACPIPMFixedEvent::SleepButton => BITSHIFT_PM1_SLPBTN,
419*bb4ee6a4SAndroid Build Coastguard Worker ACPIPMFixedEvent::RTC => BITSHIFT_PM1_RTC,
420*bb4ee6a4SAndroid Build Coastguard Worker }
421*bb4ee6a4SAndroid Build Coastguard Worker }
422*bb4ee6a4SAndroid Build Coastguard Worker
bitmask(self) -> u16423*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn bitmask(self) -> u16 {
424*bb4ee6a4SAndroid Build Coastguard Worker 1 << self.bitshift()
425*bb4ee6a4SAndroid Build Coastguard Worker }
426*bb4ee6a4SAndroid Build Coastguard Worker
bitmask_all() -> u16427*bb4ee6a4SAndroid Build Coastguard Worker fn bitmask_all() -> u16 {
428*bb4ee6a4SAndroid Build Coastguard Worker (1 << BITSHIFT_PM1_GBL)
429*bb4ee6a4SAndroid Build Coastguard Worker | (1 << BITSHIFT_PM1_PWRBTN)
430*bb4ee6a4SAndroid Build Coastguard Worker | (1 << BITSHIFT_PM1_SLPBTN)
431*bb4ee6a4SAndroid Build Coastguard Worker | (1 << BITSHIFT_PM1_RTC)
432*bb4ee6a4SAndroid Build Coastguard Worker }
433*bb4ee6a4SAndroid Build Coastguard Worker }
434*bb4ee6a4SAndroid Build Coastguard Worker
435*bb4ee6a4SAndroid Build Coastguard Worker impl FromStr for ACPIPMFixedEvent {
436*bb4ee6a4SAndroid Build Coastguard Worker type Err = &'static str;
437*bb4ee6a4SAndroid Build Coastguard Worker
from_str(s: &str) -> Result<Self, Self::Err>438*bb4ee6a4SAndroid Build Coastguard Worker fn from_str(s: &str) -> Result<Self, Self::Err> {
439*bb4ee6a4SAndroid Build Coastguard Worker match s {
440*bb4ee6a4SAndroid Build Coastguard Worker "gbllock" => Ok(ACPIPMFixedEvent::GlobalLock),
441*bb4ee6a4SAndroid Build Coastguard Worker "powerbtn" => Ok(ACPIPMFixedEvent::PowerButton),
442*bb4ee6a4SAndroid Build Coastguard Worker "sleepbtn" => Ok(ACPIPMFixedEvent::SleepButton),
443*bb4ee6a4SAndroid Build Coastguard Worker "rtc" => Ok(ACPIPMFixedEvent::RTC),
444*bb4ee6a4SAndroid Build Coastguard Worker _ => Err("unknown event, must be: gbllock|powerbtn|sleepbtn|rtc"),
445*bb4ee6a4SAndroid Build Coastguard Worker }
446*bb4ee6a4SAndroid Build Coastguard Worker }
447*bb4ee6a4SAndroid Build Coastguard Worker }
448*bb4ee6a4SAndroid Build Coastguard Worker
449*bb4ee6a4SAndroid Build Coastguard Worker impl PmResource for ACPIPMResource {
pwrbtn_evt(&mut self)450*bb4ee6a4SAndroid Build Coastguard Worker fn pwrbtn_evt(&mut self) {
451*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
452*bb4ee6a4SAndroid Build Coastguard Worker
453*bb4ee6a4SAndroid Build Coastguard Worker pm1.status |= ACPIPMFixedEvent::PowerButton.bitmask();
454*bb4ee6a4SAndroid Build Coastguard Worker pm1.trigger_sci(&self.sci_evt);
455*bb4ee6a4SAndroid Build Coastguard Worker }
456*bb4ee6a4SAndroid Build Coastguard Worker
slpbtn_evt(&mut self)457*bb4ee6a4SAndroid Build Coastguard Worker fn slpbtn_evt(&mut self) {
458*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
459*bb4ee6a4SAndroid Build Coastguard Worker
460*bb4ee6a4SAndroid Build Coastguard Worker pm1.status |= ACPIPMFixedEvent::SleepButton.bitmask();
461*bb4ee6a4SAndroid Build Coastguard Worker pm1.trigger_sci(&self.sci_evt);
462*bb4ee6a4SAndroid Build Coastguard Worker }
463*bb4ee6a4SAndroid Build Coastguard Worker
rtc_evt(&mut self, clear_evt: Event)464*bb4ee6a4SAndroid Build Coastguard Worker fn rtc_evt(&mut self, clear_evt: Event) {
465*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
466*bb4ee6a4SAndroid Build Coastguard Worker
467*bb4ee6a4SAndroid Build Coastguard Worker pm1.rtc_clear_evt = Some(clear_evt);
468*bb4ee6a4SAndroid Build Coastguard Worker pm1.status |= ACPIPMFixedEvent::RTC.bitmask();
469*bb4ee6a4SAndroid Build Coastguard Worker pm1.trigger_sci(&self.sci_evt);
470*bb4ee6a4SAndroid Build Coastguard Worker }
471*bb4ee6a4SAndroid Build Coastguard Worker
gpe_evt(&mut self, gpe: u32, clear_evt: Option<Event>)472*bb4ee6a4SAndroid Build Coastguard Worker fn gpe_evt(&mut self, gpe: u32, clear_evt: Option<Event>) {
473*bb4ee6a4SAndroid Build Coastguard Worker let mut gpe0 = self.gpe0.lock();
474*bb4ee6a4SAndroid Build Coastguard Worker match gpe0.set_active(gpe) {
475*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {
476*bb4ee6a4SAndroid Build Coastguard Worker if let Some(clear_evt) = clear_evt {
477*bb4ee6a4SAndroid Build Coastguard Worker gpe0.pending_clear_evts
478*bb4ee6a4SAndroid Build Coastguard Worker .entry(gpe)
479*bb4ee6a4SAndroid Build Coastguard Worker .or_default()
480*bb4ee6a4SAndroid Build Coastguard Worker .push(clear_evt);
481*bb4ee6a4SAndroid Build Coastguard Worker }
482*bb4ee6a4SAndroid Build Coastguard Worker gpe0.trigger_sci(&self.sci_evt)
483*bb4ee6a4SAndroid Build Coastguard Worker }
484*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => error!("{}", e),
485*bb4ee6a4SAndroid Build Coastguard Worker }
486*bb4ee6a4SAndroid Build Coastguard Worker }
487*bb4ee6a4SAndroid Build Coastguard Worker
pme_evt(&mut self, requester_id: u16)488*bb4ee6a4SAndroid Build Coastguard Worker fn pme_evt(&mut self, requester_id: u16) {
489*bb4ee6a4SAndroid Build Coastguard Worker let bus = ((requester_id >> 8) & 0xFF) as u8;
490*bb4ee6a4SAndroid Build Coastguard Worker let mut pci = self.pci.lock();
491*bb4ee6a4SAndroid Build Coastguard Worker if let Some(root_ports) = pci.pme_notify.get_mut(&bus) {
492*bb4ee6a4SAndroid Build Coastguard Worker for root_port in root_ports {
493*bb4ee6a4SAndroid Build Coastguard Worker root_port.lock().notify(requester_id);
494*bb4ee6a4SAndroid Build Coastguard Worker }
495*bb4ee6a4SAndroid Build Coastguard Worker }
496*bb4ee6a4SAndroid Build Coastguard Worker }
497*bb4ee6a4SAndroid Build Coastguard Worker
register_gpe_notify_dev(&mut self, gpe: u32, notify_dev: Arc<Mutex<dyn GpeNotify>>)498*bb4ee6a4SAndroid Build Coastguard Worker fn register_gpe_notify_dev(&mut self, gpe: u32, notify_dev: Arc<Mutex<dyn GpeNotify>>) {
499*bb4ee6a4SAndroid Build Coastguard Worker let mut gpe0 = self.gpe0.lock();
500*bb4ee6a4SAndroid Build Coastguard Worker match gpe0.gpe_notify.get_mut(&gpe) {
501*bb4ee6a4SAndroid Build Coastguard Worker Some(v) => v.push(notify_dev),
502*bb4ee6a4SAndroid Build Coastguard Worker None => {
503*bb4ee6a4SAndroid Build Coastguard Worker gpe0.gpe_notify.insert(gpe, vec![notify_dev]);
504*bb4ee6a4SAndroid Build Coastguard Worker }
505*bb4ee6a4SAndroid Build Coastguard Worker }
506*bb4ee6a4SAndroid Build Coastguard Worker }
507*bb4ee6a4SAndroid Build Coastguard Worker
register_pme_notify_dev(&mut self, bus: u8, notify_dev: Arc<Mutex<dyn PmeNotify>>)508*bb4ee6a4SAndroid Build Coastguard Worker fn register_pme_notify_dev(&mut self, bus: u8, notify_dev: Arc<Mutex<dyn PmeNotify>>) {
509*bb4ee6a4SAndroid Build Coastguard Worker let mut pci = self.pci.lock();
510*bb4ee6a4SAndroid Build Coastguard Worker match pci.pme_notify.get_mut(&bus) {
511*bb4ee6a4SAndroid Build Coastguard Worker Some(v) => v.push(notify_dev),
512*bb4ee6a4SAndroid Build Coastguard Worker None => {
513*bb4ee6a4SAndroid Build Coastguard Worker pci.pme_notify.insert(bus, vec![notify_dev]);
514*bb4ee6a4SAndroid Build Coastguard Worker }
515*bb4ee6a4SAndroid Build Coastguard Worker }
516*bb4ee6a4SAndroid Build Coastguard Worker }
517*bb4ee6a4SAndroid Build Coastguard Worker }
518*bb4ee6a4SAndroid Build Coastguard Worker
519*bb4ee6a4SAndroid Build Coastguard Worker const PM1_STATUS_LAST: u16 = PM1_STATUS + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2) - 1;
520*bb4ee6a4SAndroid Build Coastguard Worker const PM1_ENABLE_LAST: u16 = PM1_ENABLE + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2) - 1;
521*bb4ee6a4SAndroid Build Coastguard Worker const PM1_CONTROL_LAST: u16 = PM1_CONTROL + ACPIPM_RESOURCE_CONTROLBLK_LEN as u16 - 1;
522*bb4ee6a4SAndroid Build Coastguard Worker const GPE0_STATUS_LAST: u16 = GPE0_STATUS + (ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2) - 1;
523*bb4ee6a4SAndroid Build Coastguard Worker const GPE0_ENABLE_LAST: u16 = GPE0_ENABLE + (ACPIPM_RESOURCE_GPE0_BLK_LEN as u16 / 2) - 1;
524*bb4ee6a4SAndroid Build Coastguard Worker
525*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for ACPIPMResource {
device_id(&self) -> DeviceId526*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId {
527*bb4ee6a4SAndroid Build Coastguard Worker CrosvmDeviceId::ACPIPMResource.into()
528*bb4ee6a4SAndroid Build Coastguard Worker }
529*bb4ee6a4SAndroid Build Coastguard Worker
debug_label(&self) -> String530*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String {
531*bb4ee6a4SAndroid Build Coastguard Worker "ACPIPMResource".to_owned()
532*bb4ee6a4SAndroid Build Coastguard Worker }
533*bb4ee6a4SAndroid Build Coastguard Worker
read(&mut self, info: BusAccessInfo, data: &mut [u8])534*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
535*bb4ee6a4SAndroid Build Coastguard Worker match info.offset as u16 {
536*bb4ee6a4SAndroid Build Coastguard Worker // Accesses to the PM1 registers are done through byte or word accesses
537*bb4ee6a4SAndroid Build Coastguard Worker PM1_STATUS..=PM1_STATUS_LAST => {
538*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u16>()
539*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (PM1_STATUS_LAST + 1).into()
540*bb4ee6a4SAndroid Build Coastguard Worker {
541*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad read size: {}", data.len());
542*bb4ee6a4SAndroid Build Coastguard Worker return;
543*bb4ee6a4SAndroid Build Coastguard Worker }
544*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - PM1_STATUS as u64) as usize;
545*bb4ee6a4SAndroid Build Coastguard Worker
546*bb4ee6a4SAndroid Build Coastguard Worker let v = self.pm1.lock().status.to_ne_bytes();
547*bb4ee6a4SAndroid Build Coastguard Worker for (i, j) in (offset..offset + data.len()).enumerate() {
548*bb4ee6a4SAndroid Build Coastguard Worker data[i] = v[j];
549*bb4ee6a4SAndroid Build Coastguard Worker }
550*bb4ee6a4SAndroid Build Coastguard Worker }
551*bb4ee6a4SAndroid Build Coastguard Worker PM1_ENABLE..=PM1_ENABLE_LAST => {
552*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u16>()
553*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (PM1_ENABLE_LAST + 1).into()
554*bb4ee6a4SAndroid Build Coastguard Worker {
555*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad read size: {}", data.len());
556*bb4ee6a4SAndroid Build Coastguard Worker return;
557*bb4ee6a4SAndroid Build Coastguard Worker }
558*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - PM1_ENABLE as u64) as usize;
559*bb4ee6a4SAndroid Build Coastguard Worker
560*bb4ee6a4SAndroid Build Coastguard Worker let v = self.pm1.lock().enable.to_ne_bytes();
561*bb4ee6a4SAndroid Build Coastguard Worker for (i, j) in (offset..offset + data.len()).enumerate() {
562*bb4ee6a4SAndroid Build Coastguard Worker data[i] = v[j];
563*bb4ee6a4SAndroid Build Coastguard Worker }
564*bb4ee6a4SAndroid Build Coastguard Worker }
565*bb4ee6a4SAndroid Build Coastguard Worker PM1_CONTROL..=PM1_CONTROL_LAST => {
566*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u16>()
567*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (PM1_CONTROL_LAST + 1).into()
568*bb4ee6a4SAndroid Build Coastguard Worker {
569*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad read size: {}", data.len());
570*bb4ee6a4SAndroid Build Coastguard Worker return;
571*bb4ee6a4SAndroid Build Coastguard Worker }
572*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - PM1_CONTROL as u64) as usize;
573*bb4ee6a4SAndroid Build Coastguard Worker data.copy_from_slice(
574*bb4ee6a4SAndroid Build Coastguard Worker &self.pm1.lock().control.to_ne_bytes()[offset..offset + data.len()],
575*bb4ee6a4SAndroid Build Coastguard Worker );
576*bb4ee6a4SAndroid Build Coastguard Worker }
577*bb4ee6a4SAndroid Build Coastguard Worker // OSPM accesses GPE registers through byte accesses (regardless of their length)
578*bb4ee6a4SAndroid Build Coastguard Worker GPE0_STATUS..=GPE0_STATUS_LAST => {
579*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u8>()
580*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (GPE0_STATUS_LAST + 1).into()
581*bb4ee6a4SAndroid Build Coastguard Worker {
582*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad read size: {}", data.len());
583*bb4ee6a4SAndroid Build Coastguard Worker return;
584*bb4ee6a4SAndroid Build Coastguard Worker }
585*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - GPE0_STATUS as u64) as usize;
586*bb4ee6a4SAndroid Build Coastguard Worker data[0] = self.gpe0.lock().status[offset];
587*bb4ee6a4SAndroid Build Coastguard Worker }
588*bb4ee6a4SAndroid Build Coastguard Worker GPE0_ENABLE..=GPE0_ENABLE_LAST => {
589*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u8>()
590*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (GPE0_ENABLE_LAST + 1).into()
591*bb4ee6a4SAndroid Build Coastguard Worker {
592*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad read size: {}", data.len());
593*bb4ee6a4SAndroid Build Coastguard Worker return;
594*bb4ee6a4SAndroid Build Coastguard Worker }
595*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - GPE0_ENABLE as u64) as usize;
596*bb4ee6a4SAndroid Build Coastguard Worker data[0] = self.gpe0.lock().enable[offset];
597*bb4ee6a4SAndroid Build Coastguard Worker }
598*bb4ee6a4SAndroid Build Coastguard Worker _ => {
599*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: Bad read from {}", info);
600*bb4ee6a4SAndroid Build Coastguard Worker }
601*bb4ee6a4SAndroid Build Coastguard Worker }
602*bb4ee6a4SAndroid Build Coastguard Worker }
603*bb4ee6a4SAndroid Build Coastguard Worker
write(&mut self, info: BusAccessInfo, data: &[u8])604*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
605*bb4ee6a4SAndroid Build Coastguard Worker match info.offset as u16 {
606*bb4ee6a4SAndroid Build Coastguard Worker // Accesses to the PM1 registers are done through byte or word accesses
607*bb4ee6a4SAndroid Build Coastguard Worker PM1_STATUS..=PM1_STATUS_LAST => {
608*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u16>()
609*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (PM1_STATUS_LAST + 1).into()
610*bb4ee6a4SAndroid Build Coastguard Worker {
611*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad write size: {}", data.len());
612*bb4ee6a4SAndroid Build Coastguard Worker return;
613*bb4ee6a4SAndroid Build Coastguard Worker }
614*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - PM1_STATUS as u64) as usize;
615*bb4ee6a4SAndroid Build Coastguard Worker
616*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
617*bb4ee6a4SAndroid Build Coastguard Worker let mut v = pm1.status.to_ne_bytes();
618*bb4ee6a4SAndroid Build Coastguard Worker for (i, j) in (offset..offset + data.len()).enumerate() {
619*bb4ee6a4SAndroid Build Coastguard Worker v[j] &= !data[i];
620*bb4ee6a4SAndroid Build Coastguard Worker }
621*bb4ee6a4SAndroid Build Coastguard Worker pm1.status = u16::from_ne_bytes(v);
622*bb4ee6a4SAndroid Build Coastguard Worker }
623*bb4ee6a4SAndroid Build Coastguard Worker PM1_ENABLE..=PM1_ENABLE_LAST => {
624*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u16>()
625*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (PM1_ENABLE_LAST + 1).into()
626*bb4ee6a4SAndroid Build Coastguard Worker {
627*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad write size: {}", data.len());
628*bb4ee6a4SAndroid Build Coastguard Worker return;
629*bb4ee6a4SAndroid Build Coastguard Worker }
630*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - PM1_ENABLE as u64) as usize;
631*bb4ee6a4SAndroid Build Coastguard Worker
632*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
633*bb4ee6a4SAndroid Build Coastguard Worker let mut v = pm1.enable.to_ne_bytes();
634*bb4ee6a4SAndroid Build Coastguard Worker for (i, j) in (offset..offset + data.len()).enumerate() {
635*bb4ee6a4SAndroid Build Coastguard Worker v[j] = data[i];
636*bb4ee6a4SAndroid Build Coastguard Worker }
637*bb4ee6a4SAndroid Build Coastguard Worker pm1.enable = u16::from_ne_bytes(v);
638*bb4ee6a4SAndroid Build Coastguard Worker pm1.resample_clear_evts_and_trigger(&self.sci_evt);
639*bb4ee6a4SAndroid Build Coastguard Worker }
640*bb4ee6a4SAndroid Build Coastguard Worker PM1_CONTROL..=PM1_CONTROL_LAST => {
641*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u16>()
642*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (PM1_CONTROL_LAST + 1).into()
643*bb4ee6a4SAndroid Build Coastguard Worker {
644*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad write size: {}", data.len());
645*bb4ee6a4SAndroid Build Coastguard Worker return;
646*bb4ee6a4SAndroid Build Coastguard Worker }
647*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - PM1_CONTROL as u64) as usize;
648*bb4ee6a4SAndroid Build Coastguard Worker
649*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = self.pm1.lock();
650*bb4ee6a4SAndroid Build Coastguard Worker
651*bb4ee6a4SAndroid Build Coastguard Worker let mut v = pm1.control.to_ne_bytes();
652*bb4ee6a4SAndroid Build Coastguard Worker for (i, j) in (offset..offset + data.len()).enumerate() {
653*bb4ee6a4SAndroid Build Coastguard Worker v[j] = data[i];
654*bb4ee6a4SAndroid Build Coastguard Worker }
655*bb4ee6a4SAndroid Build Coastguard Worker let val = u16::from_ne_bytes(v);
656*bb4ee6a4SAndroid Build Coastguard Worker
657*bb4ee6a4SAndroid Build Coastguard Worker // SLP_EN is a write-only bit and reads to it always return a zero
658*bb4ee6a4SAndroid Build Coastguard Worker if (val & BITMASK_PM1CNT_SLEEP_ENABLE) != 0 {
659*bb4ee6a4SAndroid Build Coastguard Worker match val & BITMASK_PM1CNT_SLEEP_TYPE {
660*bb4ee6a4SAndroid Build Coastguard Worker SLEEP_TYPE_S1 => {
661*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.suspend_tube.lock().send(&true) {
662*bb4ee6a4SAndroid Build Coastguard Worker error!("ACPIPM: failed to trigger suspend event: {}", e);
663*bb4ee6a4SAndroid Build Coastguard Worker }
664*bb4ee6a4SAndroid Build Coastguard Worker }
665*bb4ee6a4SAndroid Build Coastguard Worker SLEEP_TYPE_S5 => {
666*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) =
667*bb4ee6a4SAndroid Build Coastguard Worker self.exit_evt_wrtube.send::<VmEventType>(&VmEventType::Exit)
668*bb4ee6a4SAndroid Build Coastguard Worker {
669*bb4ee6a4SAndroid Build Coastguard Worker error!("ACPIPM: failed to trigger exit event: {}", e);
670*bb4ee6a4SAndroid Build Coastguard Worker }
671*bb4ee6a4SAndroid Build Coastguard Worker }
672*bb4ee6a4SAndroid Build Coastguard Worker _ => error!(
673*bb4ee6a4SAndroid Build Coastguard Worker "ACPIPM: unknown SLP_TYP written: {}",
674*bb4ee6a4SAndroid Build Coastguard Worker (val & BITMASK_PM1CNT_SLEEP_TYPE) >> 10
675*bb4ee6a4SAndroid Build Coastguard Worker ),
676*bb4ee6a4SAndroid Build Coastguard Worker }
677*bb4ee6a4SAndroid Build Coastguard Worker }
678*bb4ee6a4SAndroid Build Coastguard Worker pm1.control = val & !BITMASK_PM1CNT_SLEEP_ENABLE;
679*bb4ee6a4SAndroid Build Coastguard Worker
680*bb4ee6a4SAndroid Build Coastguard Worker // Re-trigger PM & GPEs in case there is a pending wakeup that should
681*bb4ee6a4SAndroid Build Coastguard Worker // override us just having gone to sleep.
682*bb4ee6a4SAndroid Build Coastguard Worker pm1.resample_clear_evts_and_trigger(&self.sci_evt);
683*bb4ee6a4SAndroid Build Coastguard Worker self.gpe0
684*bb4ee6a4SAndroid Build Coastguard Worker .lock()
685*bb4ee6a4SAndroid Build Coastguard Worker .resample_clear_evts_and_trigger(&self.sci_evt);
686*bb4ee6a4SAndroid Build Coastguard Worker }
687*bb4ee6a4SAndroid Build Coastguard Worker // OSPM accesses GPE registers through byte accesses (regardless of their length)
688*bb4ee6a4SAndroid Build Coastguard Worker GPE0_STATUS..=GPE0_STATUS_LAST => {
689*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u8>()
690*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (GPE0_STATUS_LAST + 1).into()
691*bb4ee6a4SAndroid Build Coastguard Worker {
692*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad write size: {}", data.len());
693*bb4ee6a4SAndroid Build Coastguard Worker return;
694*bb4ee6a4SAndroid Build Coastguard Worker }
695*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - GPE0_STATUS as u64) as usize;
696*bb4ee6a4SAndroid Build Coastguard Worker self.gpe0.lock().status[offset] &= !data[0];
697*bb4ee6a4SAndroid Build Coastguard Worker }
698*bb4ee6a4SAndroid Build Coastguard Worker GPE0_ENABLE..=GPE0_ENABLE_LAST => {
699*bb4ee6a4SAndroid Build Coastguard Worker if data.len() > std::mem::size_of::<u8>()
700*bb4ee6a4SAndroid Build Coastguard Worker || info.offset + data.len() as u64 > (GPE0_ENABLE_LAST + 1).into()
701*bb4ee6a4SAndroid Build Coastguard Worker {
702*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: bad write size: {}", data.len());
703*bb4ee6a4SAndroid Build Coastguard Worker return;
704*bb4ee6a4SAndroid Build Coastguard Worker }
705*bb4ee6a4SAndroid Build Coastguard Worker let offset = (info.offset - GPE0_ENABLE as u64) as usize;
706*bb4ee6a4SAndroid Build Coastguard Worker let mut gpe = self.gpe0.lock();
707*bb4ee6a4SAndroid Build Coastguard Worker if gpe.enable[offset] != data[0] {
708*bb4ee6a4SAndroid Build Coastguard Worker gpe.enable[offset] = data[0];
709*bb4ee6a4SAndroid Build Coastguard Worker gpe.resample_clear_evts_and_trigger(&self.sci_evt);
710*bb4ee6a4SAndroid Build Coastguard Worker }
711*bb4ee6a4SAndroid Build Coastguard Worker }
712*bb4ee6a4SAndroid Build Coastguard Worker _ => {
713*bb4ee6a4SAndroid Build Coastguard Worker warn!("ACPIPM: Bad write to {}", info);
714*bb4ee6a4SAndroid Build Coastguard Worker }
715*bb4ee6a4SAndroid Build Coastguard Worker };
716*bb4ee6a4SAndroid Build Coastguard Worker }
717*bb4ee6a4SAndroid Build Coastguard Worker }
718*bb4ee6a4SAndroid Build Coastguard Worker
719*bb4ee6a4SAndroid Build Coastguard Worker impl BusResumeDevice for ACPIPMResource {
resume_imminent(&mut self)720*bb4ee6a4SAndroid Build Coastguard Worker fn resume_imminent(&mut self) {
721*bb4ee6a4SAndroid Build Coastguard Worker self.pm1.lock().status |= BITMASK_PM1CNT_WAKE_STATUS;
722*bb4ee6a4SAndroid Build Coastguard Worker }
723*bb4ee6a4SAndroid Build Coastguard Worker }
724*bb4ee6a4SAndroid Build Coastguard Worker
725*bb4ee6a4SAndroid Build Coastguard Worker impl Aml for ACPIPMResource {
to_aml_bytes(&self, bytes: &mut Vec<u8>)726*bb4ee6a4SAndroid Build Coastguard Worker fn to_aml_bytes(&self, bytes: &mut Vec<u8>) {
727*bb4ee6a4SAndroid Build Coastguard Worker // S1
728*bb4ee6a4SAndroid Build Coastguard Worker aml::Name::new(
729*bb4ee6a4SAndroid Build Coastguard Worker "_S1_".into(),
730*bb4ee6a4SAndroid Build Coastguard Worker &aml::Package::new(vec![&aml::ONE, &aml::ONE, &aml::ZERO, &aml::ZERO]),
731*bb4ee6a4SAndroid Build Coastguard Worker )
732*bb4ee6a4SAndroid Build Coastguard Worker .to_aml_bytes(bytes);
733*bb4ee6a4SAndroid Build Coastguard Worker
734*bb4ee6a4SAndroid Build Coastguard Worker // S5
735*bb4ee6a4SAndroid Build Coastguard Worker aml::Name::new(
736*bb4ee6a4SAndroid Build Coastguard Worker "_S5_".into(),
737*bb4ee6a4SAndroid Build Coastguard Worker &aml::Package::new(vec![&aml::ZERO, &aml::ZERO, &aml::ZERO, &aml::ZERO]),
738*bb4ee6a4SAndroid Build Coastguard Worker )
739*bb4ee6a4SAndroid Build Coastguard Worker .to_aml_bytes(bytes);
740*bb4ee6a4SAndroid Build Coastguard Worker }
741*bb4ee6a4SAndroid Build Coastguard Worker }
742*bb4ee6a4SAndroid Build Coastguard Worker
743*bb4ee6a4SAndroid Build Coastguard Worker pub const PM_WAKEUP_GPIO: u32 = 0;
744*bb4ee6a4SAndroid Build Coastguard Worker
745*bb4ee6a4SAndroid Build Coastguard Worker pub struct PmWakeupEvent {
746*bb4ee6a4SAndroid Build Coastguard Worker vm_control_tube: Arc<Mutex<Tube>>,
747*bb4ee6a4SAndroid Build Coastguard Worker pm_config: Arc<Mutex<PmConfig>>,
748*bb4ee6a4SAndroid Build Coastguard Worker }
749*bb4ee6a4SAndroid Build Coastguard Worker
750*bb4ee6a4SAndroid Build Coastguard Worker impl PmWakeupEvent {
new(vm_control_tube: Arc<Mutex<Tube>>, pm_config: Arc<Mutex<PmConfig>>) -> Self751*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(vm_control_tube: Arc<Mutex<Tube>>, pm_config: Arc<Mutex<PmConfig>>) -> Self {
752*bb4ee6a4SAndroid Build Coastguard Worker Self {
753*bb4ee6a4SAndroid Build Coastguard Worker vm_control_tube,
754*bb4ee6a4SAndroid Build Coastguard Worker pm_config,
755*bb4ee6a4SAndroid Build Coastguard Worker }
756*bb4ee6a4SAndroid Build Coastguard Worker }
757*bb4ee6a4SAndroid Build Coastguard Worker
trigger_wakeup(&self) -> anyhow::Result<Option<Event>>758*bb4ee6a4SAndroid Build Coastguard Worker pub fn trigger_wakeup(&self) -> anyhow::Result<Option<Event>> {
759*bb4ee6a4SAndroid Build Coastguard Worker if self.pm_config.lock().should_trigger_pme() {
760*bb4ee6a4SAndroid Build Coastguard Worker let event = Event::new().context("failed to create clear event")?;
761*bb4ee6a4SAndroid Build Coastguard Worker let tube = self.vm_control_tube.lock();
762*bb4ee6a4SAndroid Build Coastguard Worker tube.send(&VmRequest::Gpe {
763*bb4ee6a4SAndroid Build Coastguard Worker gpe: PM_WAKEUP_GPIO,
764*bb4ee6a4SAndroid Build Coastguard Worker clear_evt: Some(event.try_clone().context("failed to clone clear event")?),
765*bb4ee6a4SAndroid Build Coastguard Worker })
766*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to send pme")?;
767*bb4ee6a4SAndroid Build Coastguard Worker match tube.recv::<VmResponse>() {
768*bb4ee6a4SAndroid Build Coastguard Worker Ok(VmResponse::Ok) => Ok(Some(event)),
769*bb4ee6a4SAndroid Build Coastguard Worker e => bail!("pme failure {:?}", e),
770*bb4ee6a4SAndroid Build Coastguard Worker }
771*bb4ee6a4SAndroid Build Coastguard Worker } else {
772*bb4ee6a4SAndroid Build Coastguard Worker Ok(None)
773*bb4ee6a4SAndroid Build Coastguard Worker }
774*bb4ee6a4SAndroid Build Coastguard Worker }
775*bb4ee6a4SAndroid Build Coastguard Worker }
776*bb4ee6a4SAndroid Build Coastguard Worker
777*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
778*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
779*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
780*bb4ee6a4SAndroid Build Coastguard Worker
781*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
782*bb4ee6a4SAndroid Build Coastguard Worker use crate::suspendable_tests;
783*bb4ee6a4SAndroid Build Coastguard Worker
get_send_tube() -> SendTube784*bb4ee6a4SAndroid Build Coastguard Worker fn get_send_tube() -> SendTube {
785*bb4ee6a4SAndroid Build Coastguard Worker Tube::directional_pair().unwrap().0
786*bb4ee6a4SAndroid Build Coastguard Worker }
787*bb4ee6a4SAndroid Build Coastguard Worker
get_irq_evt() -> IrqLevelEvent788*bb4ee6a4SAndroid Build Coastguard Worker fn get_irq_evt() -> IrqLevelEvent {
789*bb4ee6a4SAndroid Build Coastguard Worker match crate::IrqLevelEvent::new() {
790*bb4ee6a4SAndroid Build Coastguard Worker Ok(evt) => evt,
791*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => panic!(
792*bb4ee6a4SAndroid Build Coastguard Worker "failed to create irqlevelevt: {} - panic. Can't test ACPI",
793*bb4ee6a4SAndroid Build Coastguard Worker e
794*bb4ee6a4SAndroid Build Coastguard Worker ),
795*bb4ee6a4SAndroid Build Coastguard Worker }
796*bb4ee6a4SAndroid Build Coastguard Worker }
797*bb4ee6a4SAndroid Build Coastguard Worker
modify_device(acpi: &mut ACPIPMResource)798*bb4ee6a4SAndroid Build Coastguard Worker fn modify_device(acpi: &mut ACPIPMResource) {
799*bb4ee6a4SAndroid Build Coastguard Worker {
800*bb4ee6a4SAndroid Build Coastguard Worker let mut pm1 = acpi.pm1.lock();
801*bb4ee6a4SAndroid Build Coastguard Worker pm1.enable += 1;
802*bb4ee6a4SAndroid Build Coastguard Worker }
803*bb4ee6a4SAndroid Build Coastguard Worker }
804*bb4ee6a4SAndroid Build Coastguard Worker
805*bb4ee6a4SAndroid Build Coastguard Worker suspendable_tests!(
806*bb4ee6a4SAndroid Build Coastguard Worker acpi,
807*bb4ee6a4SAndroid Build Coastguard Worker ACPIPMResource::new(
808*bb4ee6a4SAndroid Build Coastguard Worker get_irq_evt(),
809*bb4ee6a4SAndroid Build Coastguard Worker Arc::new(Mutex::new(get_send_tube())),
810*bb4ee6a4SAndroid Build Coastguard Worker get_send_tube(),
811*bb4ee6a4SAndroid Build Coastguard Worker None,
812*bb4ee6a4SAndroid Build Coastguard Worker ),
813*bb4ee6a4SAndroid Build Coastguard Worker modify_device
814*bb4ee6a4SAndroid Build Coastguard Worker );
815*bb4ee6a4SAndroid Build Coastguard Worker }
816