diff --git a/repos/os/run/ahci_bench.run b/repos/os/run/ahci_bench.run index d85e00cd0..cbefa935a 100644 --- a/repos/os/run/ahci_bench.run +++ b/repos/os/run/ahci_bench.run @@ -44,6 +44,7 @@ set config { + diff --git a/repos/os/run/ahci_blk.run b/repos/os/run/ahci_blk.run index 1025589c8..3463aeb43 100644 --- a/repos/os/run/ahci_blk.run +++ b/repos/os/run/ahci_blk.run @@ -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 { + @@ -52,12 +54,23 @@ set config { append_platform_drv_config append config { + + + + + + - + + + + + + @@ -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 diff --git a/repos/os/src/drivers/ahci/README b/repos/os/src/drivers/ahci/README index 3fe71114a..2fef17dfd 100644 --- a/repos/os/src/drivers/ahci/README +++ b/repos/os/src/drivers/ahci/README @@ -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. + +! + +The report structure is depicted by the following example. + +! +! +! +! +! diff --git a/repos/os/src/drivers/ahci/ahci.cc b/repos/os/src/drivers/ahci/ahci.cc index ccca61108..598c978a2 100644 --- a/repos/os/src/drivers/ahci/ahci.cc +++ b/repos/os/src/drivers/ahci/ahci.cc @@ -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(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()); + } + }); + } + }); +} diff --git a/repos/os/src/drivers/ahci/ahci.h b/repos/os/src/drivers/ahci/ahci.h index 951be3e01..2f530c747 100644 --- a/repos/os/src/drivers/ahci/ahci.h +++ b/repos/os/src/drivers/ahci/ahci.h @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -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 { }; } diff --git a/repos/os/src/drivers/ahci/ata_driver.h b/repos/os/src/drivers/ahci/ata_driver.h index e9d08e5a8..972e8a210 100644 --- a/repos/os/src/drivers/ahci/ata_driver.h +++ b/repos/os/src/drivers/ahci/ata_driver.h @@ -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; diff --git a/repos/os/src/drivers/ahci/main.cc b/repos/os/src/drivers/ahci/main.cc index ed15b1a03..dc096c701 100644 --- a/repos/os/src/drivers/ahci/main.cc +++ b/repos/os/src/drivers/ahci/main.cc @@ -19,6 +19,7 @@ #include #include #include +#include /* local includes */ #include @@ -175,24 +176,40 @@ struct Block::Main Genode::Attached_rom_dataspace config { env, "config" }; + Genode::Constructible reporter; + Block::Root_multiple_clients root; + Signal_handler
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) { } + } };