parent
250fd42368
commit
b37f411c3f
|
@ -44,6 +44,7 @@ set config {
|
||||||
<default-route>
|
<default-route>
|
||||||
<any-service> <parent/> <any-child/> </any-service>
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
</default-route>
|
</default-route>
|
||||||
|
<default caps="100"/>
|
||||||
<start name="timer">
|
<start name="timer">
|
||||||
<resource name="RAM" quantum="1M"/>
|
<resource name="RAM" quantum="1M"/>
|
||||||
<provides><service name="Timer"/></provides>
|
<provides><service name="Timer"/></provides>
|
||||||
|
|
|
@ -9,6 +9,7 @@ set build_components {
|
||||||
core init
|
core init
|
||||||
drivers/timer
|
drivers/timer
|
||||||
drivers/ahci
|
drivers/ahci
|
||||||
|
server/report_rom
|
||||||
test/blk/cli
|
test/blk/cli
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ set config {
|
||||||
<default-route>
|
<default-route>
|
||||||
<any-service> <parent/> <any-child/> </any-service>
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
</default-route>
|
</default-route>
|
||||||
|
<default caps="100"/>
|
||||||
<start name="timer">
|
<start name="timer">
|
||||||
<resource name="RAM" quantum="1M"/>
|
<resource name="RAM" quantum="1M"/>
|
||||||
<provides><service name="Timer"/></provides>
|
<provides><service name="Timer"/></provides>
|
||||||
|
@ -52,12 +54,23 @@ set config {
|
||||||
append_platform_drv_config
|
append_platform_drv_config
|
||||||
|
|
||||||
append 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">
|
<start name="ahci_drv">
|
||||||
<resource name="RAM" quantum="10M" />
|
<resource name="RAM" quantum="10M" />
|
||||||
<provides><service name="Block" /></provides>
|
<provides><service name="Block" /></provides>
|
||||||
<config>
|
<config atapi="yes">
|
||||||
|
<report ports="yes"/>
|
||||||
<policy label_prefix="test-ahci" device="0" />
|
<policy label_prefix="test-ahci" device="0" />
|
||||||
</config>
|
</config>
|
||||||
|
<route>
|
||||||
|
<service name="Report"> <child name="ahci_report_rom"/> </service>
|
||||||
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
|
</route>
|
||||||
</start>
|
</start>
|
||||||
<start name="test-ahci">
|
<start name="test-ahci">
|
||||||
<binary name="test-blk-cli" />
|
<binary name="test-blk-cli" />
|
||||||
|
@ -75,15 +88,16 @@ install_config $config
|
||||||
#
|
#
|
||||||
# Boot modules
|
# 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
|
append_platform_drv_boot_modules
|
||||||
|
|
||||||
build_boot_image $boot_modules
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
append qemu_args " -nographic "
|
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 ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -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=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
|
run_genode_until "Tests finished successfully!" 100
|
||||||
|
|
||||||
|
|
|
@ -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
|
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
|
device at port 1. ATAPI support is by default disabled and can be enabled by
|
||||||
setting the config attribute "atapi" to "yes".
|
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>
|
||||||
|
|
|
@ -52,12 +52,16 @@ struct Ahci
|
||||||
unsigned ready_count = 0;
|
unsigned ready_count = 0;
|
||||||
bool enable_atapi;
|
bool enable_atapi;
|
||||||
|
|
||||||
|
Signal_context_capability device_identified;
|
||||||
|
|
||||||
Ahci(Genode::Env &env, Genode::Allocator &alloc,
|
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),
|
env(env), alloc(alloc),
|
||||||
root(root), irq(root.entrypoint(), *this, &Ahci::handle_irq),
|
root(root), irq(root.entrypoint(), *this, &Ahci::handle_irq),
|
||||||
enable_atapi(support_atapi)
|
enable_atapi(support_atapi),
|
||||||
|
device_identified(device_identified)
|
||||||
{
|
{
|
||||||
info();
|
info();
|
||||||
|
|
||||||
|
@ -122,7 +126,7 @@ struct Ahci
|
||||||
try {
|
try {
|
||||||
ports[i] = new (&alloc)
|
ports[i] = new (&alloc)
|
||||||
Ata_driver(alloc, ram, root, ready_count, rm, hba,
|
Ata_driver(alloc, ram, root, ready_count, rm, hba,
|
||||||
platform_hba, i);
|
platform_hba, i, device_identified);
|
||||||
enabled = true;
|
enabled = true;
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
||||||
|
@ -168,6 +172,11 @@ struct Ahci
|
||||||
ports[port_num]->ready();
|
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)
|
long device_number(const char *model_num, const char *serial_num)
|
||||||
{
|
{
|
||||||
for (long port_num = 0; port_num < MAX_PORTS; port_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,
|
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);
|
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);
|
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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <block/component.h>
|
#include <block/component.h>
|
||||||
#include <os/attached_mmio.h>
|
#include <os/attached_mmio.h>
|
||||||
|
#include <os/reporter.h>
|
||||||
#include <util/retry.h>
|
#include <util/retry.h>
|
||||||
#include <util/reconstructible.h>
|
#include <util/reconstructible.h>
|
||||||
|
|
||||||
|
@ -36,13 +37,15 @@ struct Ahci_root
|
||||||
|
|
||||||
namespace Ahci_driver {
|
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);
|
bool avail(long device_num);
|
||||||
long device_number(char const *model_num, char const *serial_num);
|
long device_number(char const *model_num, char const *serial_num);
|
||||||
|
|
||||||
Block::Driver *claim_port(long device_num);
|
Block::Driver *claim_port(long device_num);
|
||||||
void free_port(long device_num);
|
void free_port(long device_num);
|
||||||
|
void report_ports(Genode::Reporter &reporter);
|
||||||
|
|
||||||
struct Missing_controller { };
|
struct Missing_controller { };
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ struct String
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(Genode::Output &out) const { Genode::print(out, (char const *)buf); }
|
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;
|
Io_command *io_cmd = nullptr;
|
||||||
Block::Packet_descriptor pending[32];
|
Block::Packet_descriptor pending[32];
|
||||||
|
|
||||||
|
Signal_context_capability device_identified;
|
||||||
|
|
||||||
Ata_driver(Genode::Allocator &alloc,
|
Ata_driver(Genode::Allocator &alloc,
|
||||||
Genode::Ram_session &ram,
|
Genode::Ram_session &ram,
|
||||||
Ahci_root &root,
|
Ahci_root &root,
|
||||||
|
@ -195,9 +198,10 @@ struct Ata_driver : Port_driver
|
||||||
Genode::Region_map &rm,
|
Genode::Region_map &rm,
|
||||||
Hba &hba,
|
Hba &hba,
|
||||||
Platform::Hba &platform_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),
|
: Port_driver(ram, root, sem, rm, hba, platform_hba, number),
|
||||||
alloc(alloc)
|
alloc(alloc), device_identified(device_identified)
|
||||||
{
|
{
|
||||||
Port::init();
|
Port::init();
|
||||||
identify_device();
|
identify_device();
|
||||||
|
@ -317,6 +321,8 @@ struct Ata_driver : Port_driver
|
||||||
io_cmd = new (&alloc) Dma_ext_command();
|
io_cmd = new (&alloc) Dma_ext_command();
|
||||||
|
|
||||||
ack_irq();
|
ack_irq();
|
||||||
|
|
||||||
|
Genode::Signal_transmitter(device_identified).submit();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <block/component.h>
|
#include <block/component.h>
|
||||||
#include <os/session_policy.h>
|
#include <os/session_policy.h>
|
||||||
#include <util/xml_node.h>
|
#include <util/xml_node.h>
|
||||||
|
#include <os/reporter.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <ahci.h>
|
#include <ahci.h>
|
||||||
|
@ -175,24 +176,40 @@ struct Block::Main
|
||||||
|
|
||||||
Genode::Attached_rom_dataspace config { env, "config" };
|
Genode::Attached_rom_dataspace config { env, "config" };
|
||||||
|
|
||||||
|
Genode::Constructible<Genode::Reporter> reporter;
|
||||||
|
|
||||||
Block::Root_multiple_clients root;
|
Block::Root_multiple_clients root;
|
||||||
|
|
||||||
|
Signal_handler<Main> device_identified {
|
||||||
|
env.ep(), *this, &Main::handle_device_identified };
|
||||||
|
|
||||||
Main(Genode::Env &env)
|
Main(Genode::Env &env)
|
||||||
: env(env), root(env, heap, config.xml())
|
: env(env), root(env, heap, config.xml())
|
||||||
{
|
{
|
||||||
Genode::log("--- Starting AHCI driver ---");
|
Genode::log("--- Starting AHCI driver ---");
|
||||||
bool support_atapi = config.xml().attribute_value("atapi", false);
|
bool support_atapi = config.xml().attribute_value("atapi", false);
|
||||||
try { Ahci_driver::init(env, heap, root, support_atapi); }
|
try {
|
||||||
|
Ahci_driver::init(env, heap, root, support_atapi, device_identified);
|
||||||
catch (Ahci_driver::Missing_controller) {
|
} catch (Ahci_driver::Missing_controller) {
|
||||||
Genode::error("no AHCI controller found");
|
Genode::error("no AHCI controller found");
|
||||||
env.parent().exit(~0);
|
env.parent().exit(~0);
|
||||||
}
|
} catch (Genode::Service_denied) {
|
||||||
catch (Genode::Service_denied) {
|
|
||||||
Genode::error("hardware access denied");
|
Genode::error("hardware access denied");
|
||||||
env.parent().exit(~0);
|
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) { }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user