ahci: optionally report discovered devices

Issue #2417
This commit is contained in:
Christian Helmuth 2017-05-14 17:02:59 +02:00
parent 250fd42368
commit b37f411c3f
7 changed files with 109 additions and 19 deletions

View File

@ -44,6 +44,7 @@ set config {
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>

View File

@ -9,6 +9,7 @@ set build_components {
core init
drivers/timer
drivers/ahci
server/report_rom
test/blk/cli
}
@ -44,6 +45,7 @@ set config {
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
@ -52,12 +54,23 @@ set config {
append_platform_drv_config
append config {
<start name="ahci_report_rom">
<binary name="report_rom"/>
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="yes"/>
</start>
<start name="ahci_drv">
<resource name="RAM" quantum="10M" />
<provides><service name="Block" /></provides>
<config>
<config atapi="yes">
<report ports="yes"/>
<policy label_prefix="test-ahci" device="0" />
</config>
<route>
<service name="Report"> <child name="ahci_report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="test-ahci">
<binary name="test-blk-cli" />
@ -75,15 +88,16 @@ install_config $config
#
# Boot modules
#
set boot_modules { core ld.lib.so init timer ahci_drv test-blk-cli }
set boot_modules { core ld.lib.so init timer ahci_drv report_rom test-blk-cli }
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args " -nographic "
append qemu_args " -drive id=disk,file=bin/ext2.raw,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -boot d"
append qemu_args " -drive id=cd,file=[run_dir]/../ahci_blk.iso,if=none,media=cdrom -device ide-cd,drive=cd,bus=ahci.1"
append qemu_args " -nographic -device ahci,id=ahci -boot d "
append qemu_args " -drive id=disk,file=bin/ext2.raw,format=raw,if=none -device ide-hd,drive=disk,bus=ahci.0 "
append qemu_args " -drive id=cd,file=[run_dir]/../ahci_blk.iso,if=none,media=cdrom -device ide-cd,drive=cd,bus=ahci.1 "
append qemu_args " -drive id=disk2,file=bin/ext2.raw,format=raw,if=none -device ide-hd,drive=disk2,bus=ahci.2 "
run_genode_until "Tests finished successfully!" 100

View File

@ -29,3 +29,18 @@ In the example above, a session request labeled with "test-ahci" gains access to
a device with certain model and serial numbers, while "bench" gains access to
device at port 1. ATAPI support is by default disabled and can be enabled by
setting the config attribute "atapi" to "yes".
ahci_drv supports reporting of active ports, which can be enabled via
configuration sub-node like follows.
!<report ports="yes"/>
The report structure is depicted by the following example.
! <ports>
! <port num="0" type="ATA" block_count="32768" block_size="512"
! model="QEMU HARDDISK" serial="QM00005"/>
! <port num="1" type="ATAPI"/>
! <port num="2" type="ATA" block_count="32768" block_size="512"
! model="QEMU HARDDISK" serial="QM00009"/>
! </ports>

View File

@ -52,12 +52,16 @@ struct Ahci
unsigned ready_count = 0;
bool enable_atapi;
Signal_context_capability device_identified;
Ahci(Genode::Env &env, Genode::Allocator &alloc,
Ahci_root &root, bool support_atapi)
Ahci_root &root, bool support_atapi,
Genode::Signal_context_capability device_identified)
:
env(env), alloc(alloc),
root(root), irq(root.entrypoint(), *this, &Ahci::handle_irq),
enable_atapi(support_atapi)
enable_atapi(support_atapi),
device_identified(device_identified)
{
info();
@ -122,7 +126,7 @@ struct Ahci
try {
ports[i] = new (&alloc)
Ata_driver(alloc, ram, root, ready_count, rm, hba,
platform_hba, i);
platform_hba, i, device_identified);
enabled = true;
} catch (...) { }
@ -168,6 +172,11 @@ struct Ahci
ports[port_num]->ready();
}
Port_driver * port(unsigned num)
{
return num < MAX_PORTS ? ports[num] : nullptr;
}
long device_number(const char *model_num, const char *serial_num)
{
for (long port_num = 0; port_num < MAX_PORTS; port_num++) {
@ -191,9 +200,10 @@ static Ahci *sata_ahci(Ahci *ahci = 0)
void Ahci_driver::init(Genode::Env &env, Genode::Allocator &alloc,
Ahci_root &root, bool support_atapi)
Ahci_root &root, bool support_atapi,
Genode::Signal_context_capability device_identified)
{
static Ahci ahci(env, alloc, root, support_atapi);
static Ahci ahci(env, alloc, root, support_atapi, device_identified);
sata_ahci(&ahci);
}
@ -220,3 +230,27 @@ long Ahci_driver::device_number(char const *model_num, char const *serial_num)
{
return sata_ahci()->device_number(model_num, serial_num);
}
void Ahci_driver::report_ports(Genode::Reporter &reporter)
{
Genode::Reporter::Xml_generator xml(reporter, [&] () {
for (unsigned i = 0; i < Ahci::MAX_PORTS; ++i) {
Port_driver *port = sata_ahci()->port(i);
if (!port || !port->ready()) continue;
Ata_driver *ata = dynamic_cast<Ata_driver *>(port);
xml.node("port", [&] () {
xml.attribute("num", i);
xml.attribute("type", ata ? "ATA" : "ATAPI");
if (ata) {
xml.attribute("block_count", ata->block_count());
xml.attribute("block_size", ata->block_size());
xml.attribute("model", ata->model->cstring());
xml.attribute("serial", ata->serial->cstring());
}
});
}
});
}

View File

@ -16,6 +16,7 @@
#include <block/component.h>
#include <os/attached_mmio.h>
#include <os/reporter.h>
#include <util/retry.h>
#include <util/reconstructible.h>
@ -36,13 +37,15 @@ struct Ahci_root
namespace Ahci_driver {
void init(Genode::Env &env, Genode::Allocator &alloc, Ahci_root &ep, bool support_atapi);
void init(Genode::Env &env, Genode::Allocator &alloc, Ahci_root &ep,
bool support_atapi, Genode::Signal_context_capability device_identified);
bool avail(long device_num);
long device_number(char const *model_num, char const *serial_num);
Block::Driver *claim_port(long device_num);
void free_port(long device_num);
void report_ports(Genode::Reporter &reporter);
struct Missing_controller { };
}

View File

@ -109,6 +109,7 @@ struct String
}
void print(Genode::Output &out) const { Genode::print(out, (char const *)buf); }
char const *cstring() { return buf; }
};
@ -188,6 +189,8 @@ struct Ata_driver : Port_driver
Io_command *io_cmd = nullptr;
Block::Packet_descriptor pending[32];
Signal_context_capability device_identified;
Ata_driver(Genode::Allocator &alloc,
Genode::Ram_session &ram,
Ahci_root &root,
@ -195,9 +198,10 @@ struct Ata_driver : Port_driver
Genode::Region_map &rm,
Hba &hba,
Platform::Hba &platform_hba,
unsigned number)
unsigned number,
Genode::Signal_context_capability device_identified)
: Port_driver(ram, root, sem, rm, hba, platform_hba, number),
alloc(alloc)
alloc(alloc), device_identified(device_identified)
{
Port::init();
identify_device();
@ -317,6 +321,8 @@ struct Ata_driver : Port_driver
io_cmd = new (&alloc) Dma_ext_command();
ack_irq();
Genode::Signal_transmitter(device_identified).submit();
}
break;

View File

@ -19,6 +19,7 @@
#include <block/component.h>
#include <os/session_policy.h>
#include <util/xml_node.h>
#include <os/reporter.h>
/* local includes */
#include <ahci.h>
@ -175,24 +176,40 @@ struct Block::Main
Genode::Attached_rom_dataspace config { env, "config" };
Genode::Constructible<Genode::Reporter> reporter;
Block::Root_multiple_clients root;
Signal_handler<Main> device_identified {
env.ep(), *this, &Main::handle_device_identified };
Main(Genode::Env &env)
: env(env), root(env, heap, config.xml())
{
Genode::log("--- Starting AHCI driver ---");
bool support_atapi = config.xml().attribute_value("atapi", false);
try { Ahci_driver::init(env, heap, root, support_atapi); }
catch (Ahci_driver::Missing_controller) {
bool support_atapi = config.xml().attribute_value("atapi", false);
try {
Ahci_driver::init(env, heap, root, support_atapi, device_identified);
} catch (Ahci_driver::Missing_controller) {
Genode::error("no AHCI controller found");
env.parent().exit(~0);
}
catch (Genode::Service_denied) {
} catch (Genode::Service_denied) {
Genode::error("hardware access denied");
env.parent().exit(~0);
}
}
void handle_device_identified()
{
try {
Xml_node report = config.xml().sub_node("report");
if (report.attribute_value("ports", false)) {
reporter.construct(env, "ports");
reporter->enabled(true);
Ahci_driver::report_ports(*reporter);
}
} catch (Genode::Xml_node::Nonexistent_sub_node) { }
}
};