mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
platform_drv: sync startup between acpica
- platform_drv announces a separate "Acpi" session - platform_drv waits for ROM "system" to change state to "acpi_ready" - acpica waits for "Acpi" announcement - acpica uses the platform driver via "Acpi" to reconfigure PCI devices - acpica changes "system" state to "acpi_ready" after it ready with initialization - platform_drv reacts on "system" state change to "acpi_ready" by announcing "Platform" session - drivers start to operate as usual Issue #2009
This commit is contained in:
parent
2030ae678e
commit
4e9aeb45ea
@ -119,6 +119,9 @@ proc append_platform_drv_config {} {
|
||||
<provides>
|
||||
<service name="Platform"/>}
|
||||
|
||||
append_if [have_spec acpi] config {
|
||||
<service name="Acpi"/>}
|
||||
|
||||
append_if [have_spec arm] config {
|
||||
<service name="Regulator"/>}
|
||||
|
||||
|
@ -30,13 +30,14 @@ proc platform_drv_policy {} {
|
||||
# add routing information to dynamically generate change of 'system' ROM
|
||||
proc platform_drv_add_routing {} {
|
||||
return {
|
||||
<service name="ROM" label="system"> <child name="dynamic_rom"/> </service>}
|
||||
<service name="ROM" label="system"> <child name="dynamic_rom"/> </service>
|
||||
<service name="ROM" label="acpi_ready"> <child name="acpi_state"/> </service>}
|
||||
}
|
||||
|
||||
# override default config to react on 'system' ROM changes for reset
|
||||
proc platform_drv_config_config {} {
|
||||
return {
|
||||
<config acpi="yes" system="no">}
|
||||
<config acpi="yes" system="yes">}
|
||||
}
|
||||
|
||||
append_platform_drv_build_components
|
||||
@ -66,7 +67,7 @@ set config {
|
||||
<start name="acpica">
|
||||
<!-- <binary name="debug-acpica"/> -->
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config ld_verbose="yes" reset="no" poweroff="no" report="yes">
|
||||
<config ld_verbose="yes" reset="no" poweroff="no" report="yes" acpi_ready="yes">
|
||||
<!-- required for "debug-acpica":
|
||||
<libc stdout="/dev/log">
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
@ -89,6 +90,7 @@ append config {
|
||||
<service name="Report" />
|
||||
</provides>
|
||||
<config verbose="yes">
|
||||
<policy label="platform_drv -> acpi_ready" report="acpica -> acpi_ready"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
|
@ -27,6 +27,15 @@ changes of the 'state' attribute:
|
||||
|
||||
!<system state="something"/>
|
||||
|
||||
Additionally, if the config attributes 'acpi_ready' is set to yes, the
|
||||
application generates a reports named 'acpi_ready' and set the state to
|
||||
|
||||
!<system state="acpi_ready"/>
|
||||
|
||||
after finishing the ACPI bring up. This is used by platform_drv to finally
|
||||
announce the Platform session, so that drivers can start after acpica has
|
||||
finished.
|
||||
|
||||
If the ROM changes to 'state="reset"' the application tries to reset the
|
||||
machine immediately.
|
||||
If the ROM changes to 'state="poweroff"' the application tries to poweroff
|
||||
@ -51,7 +60,7 @@ Excerpt of important parts of the acpica configuration
|
||||
!<start name="acpica">
|
||||
! <!-- <binary name="debug-acpica"/> -->
|
||||
! ...
|
||||
! <config reset="no" poweroff="no" report="yes"/>
|
||||
! <config reset="no" poweroff="no" report="yes" acpi_ready="yes"/>
|
||||
! <route>
|
||||
! <service name="ROM" label="system"> <child name="..."/> </service>
|
||||
! <service name="Report"> <child name="..."/> </service>
|
||||
|
@ -10,6 +10,7 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/component.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/signal.h>
|
||||
@ -215,6 +216,7 @@ struct Acpica::Main {
|
||||
bool enable_reset = Genode::config()->xml_node().attribute_value("reset", false);
|
||||
bool enable_poweroff = Genode::config()->xml_node().attribute_value("poweroff", false);
|
||||
bool enable_report = Genode::config()->xml_node().attribute_value("report", false);
|
||||
bool enable_ready = Genode::config()->xml_node().attribute_value("acpi_ready", false);
|
||||
|
||||
if (enable_report)
|
||||
_report = new (Genode::env()->heap()) Acpica::Reportstate();
|
||||
@ -229,16 +231,29 @@ struct Acpica::Main {
|
||||
enable_poweroff);
|
||||
|
||||
/* setup IRQ */
|
||||
if (irq_handler.handler) {
|
||||
_sci_conn.construct(irq_handler.irq);
|
||||
|
||||
PINF("SCI IRQ: %u", irq_handler.irq);
|
||||
|
||||
_sci_conn->sigh(_sci_irq);
|
||||
_sci_conn->ack_irq();
|
||||
} else
|
||||
if (!irq_handler.handler) {
|
||||
PWRN("no IRQ handling available");
|
||||
return;
|
||||
}
|
||||
|
||||
_sci_conn.construct(irq_handler.irq);
|
||||
|
||||
PINF("SCI IRQ: %u", irq_handler.irq);
|
||||
|
||||
_sci_conn->sigh(_sci_irq);
|
||||
_sci_conn->ack_irq();
|
||||
|
||||
if (!enable_ready)
|
||||
return;
|
||||
|
||||
/* we are ready - signal it via changing system state */
|
||||
const char * system_file = "system";
|
||||
|
||||
static Genode::Reporter _system_rom { "system", "acpi_ready" };
|
||||
_system_rom.enabled(true);
|
||||
Genode::Reporter::Xml_generator xml(_system_rom, [&] () {
|
||||
xml.attribute("state", "acpi_ready");
|
||||
});
|
||||
}
|
||||
|
||||
void acpi_irq()
|
||||
|
@ -12,20 +12,46 @@
|
||||
*/
|
||||
|
||||
#include <base/printf.h>
|
||||
#include <platform_session/connection.h>
|
||||
#include <base/env.h>
|
||||
#include <parent/parent.h>
|
||||
#include <platform_session/client.h>
|
||||
|
||||
extern "C" {
|
||||
#include "acpi.h"
|
||||
#include "acpiosxf.h"
|
||||
}
|
||||
|
||||
|
||||
static Platform::Client & platform()
|
||||
{
|
||||
static bool connected = false;
|
||||
|
||||
typedef Genode::Capability<Platform::Session> Platform_session_capability;
|
||||
Platform_session_capability platform_cap;
|
||||
|
||||
if (!connected) {
|
||||
Genode::Parent::Service_name announce_for_acpica("Acpi");
|
||||
Genode::Native_capability cap = Genode::env()->parent()->session(announce_for_acpica, "ram_quota=20K");
|
||||
|
||||
platform_cap = Genode::reinterpret_cap_cast<Platform::Session>(cap);
|
||||
connected = true;
|
||||
}
|
||||
|
||||
static Platform::Client conn(platform_cap);
|
||||
return conn;
|
||||
}
|
||||
|
||||
ACPI_STATUS AcpiOsInitialize (void)
|
||||
{
|
||||
/* XXX - acpi_drv uses IOMEM concurrently to us - wait until it is done */
|
||||
/* acpi_drv uses IOMEM concurrently to us - wait until it is done */
|
||||
PINF("wait for platform drv");
|
||||
try {
|
||||
Platform::Connection conn;
|
||||
} catch (...) { PERR("did not get Platform connection"); }
|
||||
platform();
|
||||
} catch (...) {
|
||||
PERR("did not get Platform connection");
|
||||
Genode::Lock lock(Genode::Lock::LOCKED);
|
||||
lock.lock();
|
||||
}
|
||||
PINF("wait for platform drv - done");
|
||||
return AE_OK;
|
||||
}
|
||||
@ -33,8 +59,7 @@ ACPI_STATUS AcpiOsInitialize (void)
|
||||
ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
UINT64 *value, UINT32 width)
|
||||
{
|
||||
Platform::Connection conn;
|
||||
Platform::Device_capability cap = conn.first_device();
|
||||
Platform::Device_capability cap = platform().first_device();
|
||||
|
||||
while (cap.valid()) {
|
||||
Platform::Device_client client(cap);
|
||||
@ -58,7 +83,7 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
break;
|
||||
default:
|
||||
PERR("%s : unsupported access size %u", __func__, width);
|
||||
conn.release_device(client);
|
||||
platform().release_device(client);
|
||||
return AE_ERROR;
|
||||
};
|
||||
|
||||
@ -67,13 +92,13 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
PINF("%s: %x:%x.%x reg=0x%x width=%u -> value=0x%llx",
|
||||
__func__, bus, dev, fn, reg, width, *value);
|
||||
|
||||
conn.release_device(client);
|
||||
platform().release_device(client);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
cap = conn.next_device(cap);
|
||||
cap = platform().next_device(cap);
|
||||
|
||||
conn.release_device(client);
|
||||
platform().release_device(client);
|
||||
}
|
||||
|
||||
PERR("%s unknown device - segment=%u bdf=%x:%x.%x reg=0x%x width=0x%x",
|
||||
@ -86,8 +111,7 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
UINT64 value, UINT32 width)
|
||||
{
|
||||
Platform::Connection conn;
|
||||
Platform::Device_capability cap = conn.first_device();
|
||||
Platform::Device_capability cap = platform().first_device();
|
||||
|
||||
while (cap.valid()) {
|
||||
Platform::Device_client client(cap);
|
||||
@ -111,7 +135,7 @@ ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
break;
|
||||
default:
|
||||
PERR("%s : unsupported access size %u", __func__, width);
|
||||
conn.release_device(client);
|
||||
platform().release_device(client);
|
||||
return AE_ERROR;
|
||||
};
|
||||
|
||||
@ -120,13 +144,13 @@ ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
PWRN("%s: %x:%x.%x reg=0x%x width=%u value=0x%llx",
|
||||
__func__, bus, dev, fn, reg, width, value);
|
||||
|
||||
conn.release_device(client);
|
||||
platform().release_device(client);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
cap = conn.next_device(cap);
|
||||
cap = platform().next_device(cap);
|
||||
|
||||
conn.release_device(client);
|
||||
platform().release_device(client);
|
||||
}
|
||||
|
||||
PERR("%s unknown device - segment=%u bdf=%x:%x.%x reg=0x%x width=0x%x",
|
||||
|
@ -98,8 +98,8 @@ in the following:
|
||||
!<start name="platform_drv">
|
||||
! ...
|
||||
! <route>
|
||||
! <service name="ROM">
|
||||
! <if-arg key="label" value="acpi"/> <child name="acpi_report_rom"/>
|
||||
! <service name="ROM" label="acpi">
|
||||
! <child name="acpi_report_rom"/>
|
||||
! </service>
|
||||
! ...
|
||||
! </route>
|
||||
@ -111,26 +111,56 @@ configured to not wait for the acpi report:
|
||||
|
||||
!<start name="platform_drv">
|
||||
! ...
|
||||
! <config acpi="no">
|
||||
! <config acpi="no" system="no">
|
||||
! ...
|
||||
! </config>
|
||||
! ...
|
||||
|
||||
Synchronize ACPI startup and platform driver
|
||||
--------------------------------------------
|
||||
|
||||
If the config attribute 'system' is set to 'yes', the platform driver monitors
|
||||
a ROM in XML format named 'system'.
|
||||
|
||||
!<start name="platform_drv">
|
||||
! <config acpi="yes" system="yes">
|
||||
|
||||
Additionally, the platform driver will announce the service as 'Acpi' first.
|
||||
An ACPI application like acpica can connect to the platform driver and may
|
||||
reconfigure hardware devices according to the ACPI table findings. If the
|
||||
system state changes to "acpi_ready in the XML ROM 'acpi_ready':
|
||||
|
||||
!<system state="acpi_ready"/>
|
||||
|
||||
the platform driver will announce the platform session, so that drivers may
|
||||
start to operate with the platform driver.
|
||||
|
||||
Hardware reset
|
||||
--------------
|
||||
If the attribute 'state' in the system XML ROM turns to 'reset'
|
||||
|
||||
!<system state="reset"/>
|
||||
|
||||
the platform driver will try to reset the machine, if the required I/O ports
|
||||
are owned by it.
|
||||
|
||||
Supported PCI class aliases
|
||||
---------------------------
|
||||
|
||||
The following class names are supported which corresponds to the
|
||||
specified PCI class(C), subclass(S) and programming interface(P):
|
||||
|
||||
alias C S P
|
||||
*********************
|
||||
ALL 0x0 0x00 0x0
|
||||
AHCI 0x1 0x06 0x0
|
||||
AUDIO 0x4 0x00 0x0
|
||||
ETHERNET 0x2 0x00 0x0
|
||||
USB 0xc 0x03 0x0
|
||||
VGA 0x3 0x00 0x0
|
||||
WIFI 0x2 0x80 0x0
|
||||
alias C S P
|
||||
**********************
|
||||
ALL 0x0 0x00 0x0
|
||||
AHCI 0x1 0x06 0x0
|
||||
AUDIO 0x4 0x01 0x0
|
||||
ETHERNET 0x2 0x00 0x0
|
||||
HDAUDIO 0x4 0x03 0x0
|
||||
USB 0xc 0x03 0x0
|
||||
VGA 0x3 0x00 0x0
|
||||
WIFI 0x2 0x80 0x0
|
||||
ISABRIDGE 0x6 0x01 0x0
|
||||
|
||||
|
||||
Supported non PCI devices
|
||||
|
@ -40,10 +40,15 @@ struct Platform::Main
|
||||
Genode::Lazy_volatile_object<Platform::Root> root;
|
||||
|
||||
Genode::Lazy_volatile_object<Genode::Attached_rom_dataspace> system_state;
|
||||
Genode::Lazy_volatile_object<Genode::Attached_rom_dataspace> acpi_ready;
|
||||
|
||||
Genode::Signal_handler<Platform::Main> _acpi_report;
|
||||
Genode::Signal_handler<Platform::Main> _system_report;
|
||||
|
||||
Genode::Capability<Genode::Typed_root<Platform::Session_component> > root_cap;
|
||||
|
||||
bool _system_rom = false;
|
||||
|
||||
void acpi_update()
|
||||
{
|
||||
acpi_rom->update();
|
||||
@ -54,24 +59,50 @@ struct Platform::Main
|
||||
const char * report_addr = acpi_rom->local_addr<const char>();
|
||||
|
||||
root.construct(_env, &sliced_heap, report_addr);
|
||||
_env.parent().announce(_env.ep().manage(*root));
|
||||
|
||||
root_cap = _env.ep().manage(*root);
|
||||
|
||||
if (_system_rom) {
|
||||
Genode::Parent::Service_name announce_for_acpi("Acpi");
|
||||
_env.parent().announce(announce_for_acpi, root_cap);
|
||||
} else
|
||||
_env.parent().announce(root_cap);
|
||||
}
|
||||
|
||||
void system_update()
|
||||
{
|
||||
system_state->update();
|
||||
|
||||
if (!system_state->is_valid() || !root.is_constructed())
|
||||
if (!_system_rom || !system_state.is_constructed() ||
|
||||
!acpi_ready.is_constructed())
|
||||
return;
|
||||
|
||||
Genode::Xml_node system(system_state->local_addr<char>(),
|
||||
system_state->size());
|
||||
system_state->update();
|
||||
acpi_ready->update();
|
||||
|
||||
typedef Genode::String<16> Value;
|
||||
const Value state = system.attribute_value("state", Value("unknown"));
|
||||
if (!root.is_constructed())
|
||||
return;
|
||||
|
||||
if (state == "reset")
|
||||
root->system_reset();
|
||||
if (system_state->is_valid()) {
|
||||
Genode::Xml_node system(system_state->local_addr<char>(),
|
||||
system_state->size());
|
||||
|
||||
typedef Genode::String<16> Value;
|
||||
const Value state = system.attribute_value("state", Value("unknown"));
|
||||
|
||||
if (state == "reset")
|
||||
root->system_reset();
|
||||
}
|
||||
if (acpi_ready->is_valid()) {
|
||||
Genode::Xml_node system(acpi_ready->local_addr<char>(),
|
||||
acpi_ready->size());
|
||||
|
||||
typedef Genode::String<16> Value;
|
||||
const Value state = system.attribute_value("state", Value("unknown"));
|
||||
|
||||
if (state == "acpi_ready" && root_cap.valid()) {
|
||||
_env.parent().announce(root_cap);
|
||||
root_cap = Genode::Capability<Genode::Typed_root<Platform::Session_component> > ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Main(Genode::Env &env)
|
||||
@ -83,22 +114,26 @@ struct Platform::Main
|
||||
{
|
||||
const Genode::Xml_node &config = Genode::config()->xml_node();
|
||||
|
||||
_system_rom = config.attribute_value("system", false);
|
||||
|
||||
typedef Genode::String<8> Value;
|
||||
Value const wait_for_acpi = config.attribute_value("acpi", Value("yes"));
|
||||
|
||||
if (wait_for_acpi == "yes") {
|
||||
bool system_reset = config.attribute_value("system", false);
|
||||
if (system_reset) {
|
||||
/* wait for system state changes and react upon, e.g. reset */
|
||||
system_state.construct("system");
|
||||
system_state->sigh(_system_report);
|
||||
}
|
||||
if (_system_rom) {
|
||||
/* wait for system state changes, e.g. reset and acpi_ready */
|
||||
system_state.construct("system");
|
||||
system_state->sigh(_system_report);
|
||||
acpi_ready.construct("acpi_ready");
|
||||
acpi_ready->sigh(_system_report);
|
||||
}
|
||||
|
||||
if (wait_for_acpi == "yes") {
|
||||
/* for ACPI support, wait for the first valid acpi report */
|
||||
acpi_rom.construct("acpi");
|
||||
acpi_rom->sigh(_acpi_report);
|
||||
/* check if already valid */
|
||||
acpi_update();
|
||||
system_update();
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user