L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
pm.h
1/*
2 * Copyright (C) 2018, 2026 Kernkonzept GmbH.
3 * Author(s): Jakub Jermar <jakub.jermar@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7
8#pragma once
9
10#include <l4/re/event_enums.h>
11#include <l4/re/error_helper>
12#include <l4/re/util/event>
13#include <l4/vbus/vbus>
14#include <l4/vbus/vbus_inhibitor.h>
15#include <l4/cxx/unique_ptr>
16
17#include <l4/libblock-device/debug.h>
18#include <l4/libblock-device/types.h>
19
20namespace Block_device {
21
25class Pm : public L4::Irqep_t<Pm>
26{
27public:
28 Pm(L4::Ipc::String<> const &reason) : _reason(reason)
29 {}
30
31 int init(L4::Cap<L4Re::Inhibitor> inhib)
32 {
33 auto event = cxx::make_unique<L4Re::Util::Event>();
34
35 _inhib = inhib;
36 if (!_inhib.is_valid())
37 {
38 Dbg::warn().printf("Invalid inhibitor capability.\n");
39 return -L4_ENOENT;
40 }
41 int ret =
43 if (ret)
44 {
45 Dbg::warn().printf("Failed to initialize events.\n");
46 return ret;
47 }
48 if (!event->irq().is_valid())
49 {
50 Dbg::warn().printf("Invalid event's irq capability.\n");
51 return -L4_EINVAL;
52 }
53 ret = _inhib->acquire(L4VBUS_INHIBITOR_SHUTDOWN, _reason);
54 if (ret)
55 {
56 Dbg::warn().printf("Failed to acquire shutdown inhibitor.\n");
57 return ret;
58 }
59 ret = _inhib->acquire(L4VBUS_INHIBITOR_SUSPEND, _reason);
60 if (ret)
61 {
62 Dbg::warn().printf("Failed to acquire suspend inhibitor.\n");
63 if (_inhib->release(L4VBUS_INHIBITOR_SHUTDOWN))
64 Dbg::warn().printf("Failed to release shutdown inhibitor.\n");
65 return ret;
66 }
67 _event = cxx::move(event);
68 return L4_EOK;
69 }
70
71 ~Pm()
72 {
73 if (!_event)
74 return;
75
76 if (_inhib.is_valid())
77 {
78 if (_inhib->release(L4VBUS_INHIBITOR_SHUTDOWN))
79 Dbg::warn().printf("Failed to release shutdown inhibitor.\n");
80 if (_inhib->release(L4VBUS_INHIBITOR_SUSPEND))
81 Dbg::warn().printf("Failed to release suspend inhibitor.\n");
82 }
83 }
84
85 template <typename REG>
86 void register_obj(REG *registry)
87 {
88 static_cast<void>(
89 registry->register_obj(this, L4::cap_cast<L4::Irq>(_event->irq())));
90 }
91
92 template <typename REG>
93 void unregister_obj(REG *registry)
94 {
95 registry->unregister_obj(this);
96 }
97
98 void handle_irq()
99 {
100 L4Re::Util::Event_buffer::Event *e;
101 while ((e = _event->buffer().next()) != NULL)
102 {
103 if (e->payload.type == L4RE_EV_PM)
104 {
105 switch (e->payload.code)
106 {
107 case L4VBUS_INHIBITOR_SUSPEND:
108 {
109 if (_inhib->acquire(L4VBUS_INHIBITOR_WAKEUP, _reason))
110 {
111 Dbg::warn().printf("Failed to acquire wakeup inhibitor "
112 "lock, blocking suspend.\n");
113 break;
114 }
115 suspend();
116 if (_inhib->release(L4VBUS_INHIBITOR_SUSPEND))
117 Dbg::warn().printf(
118 "Failed to release suspend inhibitor lock.\n");
119 break;
120 }
121 case L4VBUS_INHIBITOR_SHUTDOWN:
122 {
123 shutdown();
124 if (_inhib->release(L4VBUS_INHIBITOR_SHUTDOWN))
125 Dbg::warn().printf(
126 "Failed to release shutdown inhibitor lock.\n");
127 break;
128 }
129 case L4VBUS_INHIBITOR_WAKEUP:
130 {
131 if (_inhib->acquire(L4VBUS_INHIBITOR_SUSPEND, _reason))
132 {
133 Dbg::warn().printf("Failed to acquire suspend inhibitor "
134 "lock, blocking wakeup.\n");
135 break;
136 }
137 wakeup();
138 if (_inhib->release(L4VBUS_INHIBITOR_WAKEUP))
139 Dbg::warn().printf(
140 "Failed to release wakeup inhibitor lock.\n");
141 break;
142 }
143 default:
144 Dbg::warn().printf("Unexpected pm event.\n");
145 }
146 }
147 e->free();
148 }
149 }
150
151 virtual void suspend() = 0;
152 virtual void shutdown() = 0;
153 virtual void wakeup() = 0;
154
155private:
156 L4::Ipc::String<> _reason;
157 cxx::unique_ptr<L4Re::Util::Event> _event;
159};
160
164template <typename DM>
165class Pm_for_dm : public Pm
166{
167public:
168 Pm_for_dm(DM &dm, L4::Ipc::String<> const &reason) : Pm(reason), _dm(dm)
169 {}
170
171 void shutdown() override
172 { _dm.shutdown_event(Shutdown_type::System_shutdown); }
173 void suspend() override
174 { _dm.shutdown_event(Shutdown_type::System_suspend); }
175 void wakeup() override
176 { _dm.shutdown_event(Shutdown_type::Running); }
177
178private:
179 DM &_dm;
180};
181
182}
183
C++ interface for capabilities.
Definition capability.h:249
C++ Irq interface, see IRQs for the C interface.
Definition irq:121
Error helper.
@ L4_ENOENT
No such entity.
Definition err.h:35
@ L4_EINVAL
Invalid argument.
Definition err.h:47
@ L4_EOK
Ok.
Definition err.h:33
Cap< T > cap_reinterpret_cast(Cap< F > const &c) noexcept
reinterpret_cast for capabilities.
Definition capability.h:468
Cap< T > cap_cast(Cap< F > const &c) noexcept
static_cast for capabilities.
Definition capability.h:437
unsigned short code
Code of event.
Definition event:237
unsigned short type
Type of event.
Definition event:236
Epiface implementation for interrupt handlers.
Definition ipc_epiface:401