ahci: transition to the new base API

Issue #1987
This commit is contained in:
Josef Söntgen 2016-05-29 09:50:14 +02:00 committed by Christian Helmuth
parent c77f146e72
commit 0d8d8de42c
7 changed files with 105 additions and 71 deletions

View File

@ -31,6 +31,9 @@ Mmio::Delayer &Hba::delayer()
struct Ahci struct Ahci
{ {
Genode::Env &env;
Genode::Allocator &alloc;
/* read device signature */ /* read device signature */
enum Signature { enum Signature {
ATA_SIG = 0x101, ATA_SIG = 0x101,
@ -39,7 +42,7 @@ struct Ahci
}; };
Ahci_root &root; Ahci_root &root;
Platform::Hba &platform_hba = Platform::init(Hba::delayer()); Platform::Hba &platform_hba = Platform::init(env, Hba::delayer());
Hba hba = { platform_hba }; Hba hba = { platform_hba };
enum { MAX_PORTS = 32 }; enum { MAX_PORTS = 32 };
@ -51,10 +54,13 @@ struct Ahci
unsigned ready_count = 0; unsigned ready_count = 0;
bool enable_atapi; bool enable_atapi;
Ahci(Ahci_root &root, bool support_atapi) Ahci(Genode::Env &env, Genode::Allocator &alloc,
: root(root), irq(root.entrypoint(), *this, &Ahci::handle_irq), Ahci_root &root, bool support_atapi)
device_ready(root.entrypoint(), *this, &Ahci::ready), :
enable_atapi(support_atapi) env(env), alloc(alloc),
root(root), irq(root.entrypoint(), *this, &Ahci::handle_irq),
device_ready(root.entrypoint(), *this, &Ahci::ready),
enable_atapi(support_atapi)
{ {
info(); info();
@ -65,7 +71,7 @@ struct Ahci
hba.init(); hba.init();
/* search for devices */ /* search for devices */
scan_ports(); scan_ports(env.rm());
} }
bool atapi(unsigned sig) bool atapi(unsigned sig)
@ -118,7 +124,7 @@ struct Ahci
PINF("\t64 bit support: %s", hba.supports_64bit() ? "yes" : "no"); PINF("\t64 bit support: %s", hba.supports_64bit() ? "yes" : "no");
} }
void scan_ports() void scan_ports(Genode::Region_map &rm)
{ {
PINF("\tnumber of ports: %u pi: %x", hba.port_count(), hba.read<Hba::Pi>()); PINF("\tnumber of ports: %u pi: %x", hba.port_count(), hba.read<Hba::Pi>());
unsigned available = hba.read<Hba::Pi>(); unsigned available = hba.read<Hba::Pi>();
@ -128,7 +134,7 @@ struct Ahci
if (!(available & (1U << i))) if (!(available & (1U << i)))
continue; continue;
Port port(hba, platform_hba, i); Port port(rm, hba, platform_hba, i);
/* check for ATA/ATAPI devices */ /* check for ATA/ATAPI devices */
unsigned sig = port.read<Port::Sig>(); unsigned sig = port.read<Port::Sig>();
@ -152,13 +158,13 @@ struct Ahci
switch (sig) { switch (sig) {
case ATA_SIG: case ATA_SIG:
ports[i] = new (Genode::env()->heap()) Ata_driver(port, device_ready); ports[i] = new (&alloc) Ata_driver(alloc, port, device_ready);
ready_count++; ready_count++;
break; break;
case ATAPI_SIG: case ATAPI_SIG:
case ATAPI_SIG_QEMU: case ATAPI_SIG_QEMU:
ports[i] = new (Genode::env()->heap()) Atapi_driver(port, device_ready); ports[i] = new (&alloc) Atapi_driver(port, device_ready);
ready_count++; ready_count++;
break; break;
@ -210,9 +216,10 @@ static Ahci *sata_ahci(Ahci *ahci = 0)
} }
void Ahci_driver::init(Ahci_root &root, bool support_atapi) void Ahci_driver::init(Genode::Env &env, Genode::Allocator &alloc,
Ahci_root &root, bool support_atapi)
{ {
static Ahci ahci(root, support_atapi); static Ahci ahci(env, alloc, root, support_atapi);
sata_ahci(&ahci); sata_ahci(&ahci);
} }

View File

@ -23,7 +23,7 @@ static bool constexpr verbose = false;
namespace Platform { namespace Platform {
struct Hba; struct Hba;
Hba &init(Genode::Mmio::Delayer &delayer); Hba &init(Genode::Env &env, Genode::Mmio::Delayer &delayer);
}; };
@ -36,7 +36,7 @@ struct Ahci_root
namespace Ahci_driver { namespace Ahci_driver {
void init(Ahci_root &ep, bool support_atapi); void init(Genode::Env &env, Genode::Allocator &alloc, Ahci_root &ep, bool support_atapi);
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);
@ -393,6 +393,7 @@ struct Port : Genode::Mmio
{ {
struct Not_ready : Genode::Exception { }; struct Not_ready : Genode::Exception { };
Genode::Region_map &rm;
Hba &hba; Hba &hba;
Platform::Hba &platform_hba; Platform::Hba &platform_hba;
@ -417,9 +418,11 @@ struct Port : Genode::Mmio
State state = NONE; State state = NONE;
Port(Hba &hba, Platform::Hba &platform_hba, unsigned number) Port(Genode::Region_map &rm, Hba &hba, Platform::Hba &platform_hba,
: Mmio(hba.base + offset() + (number * size())), hba(hba), unsigned number)
platform_hba(platform_hba) :
Mmio(hba.base + offset() + (number * size())),
rm(rm), hba(hba), platform_hba(platform_hba)
{ {
stop(); stop();
if (!wait_for<Cmd::Cr>(0, Hba::delayer(), 500, 1000)) if (!wait_for<Cmd::Cr>(0, Hba::delayer(), 500, 1000))
@ -429,17 +432,17 @@ struct Port : Genode::Mmio
virtual ~Port() virtual ~Port()
{ {
if (device_ds.valid()) { if (device_ds.valid()) {
Genode::env()->rm_session()->detach((void *)cmd_list); rm.detach((void *)cmd_list);
platform_hba.free_dma_buffer(device_ds); platform_hba.free_dma_buffer(device_ds);
} }
if (cmd_ds.valid()) { if (cmd_ds.valid()) {
Genode::env()->rm_session()->detach((void *)cmd_table); rm.detach((void *)cmd_table);
platform_hba.free_dma_buffer(cmd_ds); platform_hba.free_dma_buffer(cmd_ds);
} }
if (device_info_ds.valid()) { if (device_info_ds.valid()) {
Genode::env()->rm_session()->detach((void*)device_info); rm.detach((void*)device_info);
platform_hba.free_dma_buffer(device_info_ds); platform_hba.free_dma_buffer(device_info_ds);
} }
} }
@ -743,7 +746,7 @@ struct Port : Genode::Mmio
/* command list 1K */ /* command list 1K */
addr_t phys = Genode::Dataspace_client(device_ds).phys_addr(); addr_t phys = Genode::Dataspace_client(device_ds).phys_addr();
cmd_list = (addr_t)Genode::env()->rm_session()->attach(device_ds); cmd_list = (addr_t)rm.attach(device_ds);
command_list_base(phys); command_list_base(phys);
/* receive FIS base 256 byte */ /* receive FIS base 256 byte */
@ -753,7 +756,7 @@ struct Port : Genode::Mmio
/* command table */ /* command table */
size_t cmd_size = Genode::align_addr(cmd_slots * Command_table::size(), 12); size_t cmd_size = Genode::align_addr(cmd_slots * Command_table::size(), 12);
cmd_ds = platform_hba.alloc_dma_buffer(cmd_size); cmd_ds = platform_hba.alloc_dma_buffer(cmd_size);
cmd_table = (addr_t)Genode::env()->rm_session()->attach(cmd_ds); cmd_table = (addr_t)rm.attach(cmd_ds);
phys = (addr_t)Genode::Dataspace_client(cmd_ds).phys_addr(); phys = (addr_t)Genode::Dataspace_client(cmd_ds).phys_addr();
/* set command table addresses in command list */ /* set command table addresses in command list */
@ -764,7 +767,7 @@ struct Port : Genode::Mmio
/* dataspace for device info */ /* dataspace for device info */
device_info_ds = platform_hba.alloc_dma_buffer(0x1000); device_info_ds = platform_hba.alloc_dma_buffer(0x1000);
device_info = Genode::env()->rm_session()->attach(device_info_ds); device_info = rm.attach(device_info_ds);
} }
Genode::addr_t command_table_addr(unsigned slot) Genode::addr_t command_table_addr(unsigned slot)

View File

@ -172,6 +172,8 @@ struct Dma_ext_command : Io_command
*/ */
struct Ata_driver : Port_driver struct Ata_driver : Port_driver
{ {
Genode::Allocator &alloc;
typedef ::String<Identity::Serial_number> Serial_string; typedef ::String<Identity::Serial_number> Serial_string;
typedef ::String<Identity::Model_number> Model_string; typedef ::String<Identity::Model_number> Model_string;
@ -182,8 +184,9 @@ 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];
Ata_driver(Port &port, Signal_context_capability state_change) Ata_driver(Genode::Allocator &alloc,
: Port_driver(port, state_change) Port &port, Signal_context_capability state_change)
: Port_driver(port, state_change), alloc(alloc)
{ {
Port::init(); Port::init();
identify_device(); identify_device();
@ -192,7 +195,7 @@ struct Ata_driver : Port_driver
~Ata_driver() ~Ata_driver()
{ {
if (io_cmd) if (io_cmd)
destroy (Genode::env()->heap(), io_cmd); destroy(&alloc, io_cmd);
} }
unsigned find_free_cmd_slot() unsigned find_free_cmd_slot()
@ -296,9 +299,9 @@ struct Ata_driver : Port_driver
check_device(); check_device();
if (ncq_support()) if (ncq_support())
io_cmd = new (Genode::env()->heap()) Ncq_command(); io_cmd = new (&alloc) Ncq_command();
else else
io_cmd = new (Genode::env()->heap()) Dma_ext_command(); io_cmd = new (&alloc) Dma_ext_command();
ack_irq(); ack_irq();
} }

View File

@ -5,22 +5,27 @@
*/ */
/* /*
* Copyright (C) 2015 Genode Labs GmbH * Copyright (C) 2016 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */
#include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/log.h>
#include <block/component.h> #include <block/component.h>
#include <os/config.h>
#include <os/server.h>
#include <util/xml_node.h> #include <util/xml_node.h>
#include "ahci.h" /* local includes */
#include <ahci.h>
namespace Block { namespace Block {
class Factory; class Factory;
class Root_multiple_clients; class Root_multiple_clients;
class Main;
} }
@ -59,13 +64,15 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
{ {
private: private:
Server::Entrypoint &_ep; Genode::Env &_env;
Genode::Allocator &_alloc;
Genode::Xml_node _config;
long _device_num(const char *session_label, char *model, char *sn, size_t bufs_len) long _device_num(const char *session_label, char *model, char *sn, size_t bufs_len)
{ {
long num = -1; long num = -1;
Xml_node policy = config()->xml_node().sub_node("policy"); Xml_node policy = _config.sub_node("policy");
for (;; policy = policy.next("policy")) { for (;; policy = policy.next("policy")) {
char label_buf[64]; char label_buf[64];
@ -121,48 +128,56 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
throw Root::Unavailable(); throw Root::Unavailable();
} }
Factory *factory = new (Genode::env()->heap()) Factory(num); Factory *factory = new (&_alloc) Factory(num);
return new (md_alloc()) ::Session_component(*factory, return new (&_alloc) ::Session_component(*factory,
_ep, tx_buf_size); _env.ep(), tx_buf_size);
} }
void _destroy_session(::Session_component *session) void _destroy_session(::Session_component *session)
{ {
Driver_factory &factory = session->factory(); Driver_factory &factory = session->factory();
destroy(env()->heap(), session); destroy(&_alloc, session);
destroy(env()->heap(), &factory); destroy(&_alloc, &factory);
} }
public: public:
Root_multiple_clients(Server::Entrypoint &ep, Allocator *md_alloc) Root_multiple_clients(Genode::Env &env, Genode::Allocator &alloc,
: Root_component(&ep.rpc_ep(), md_alloc), _ep(ep) { } Genode::Xml_node config)
:
Root_component(&env.ep().rpc_ep(), &alloc),
_env(env), _alloc(alloc), _config(config)
{ }
Server::Entrypoint &entrypoint() override { return _ep; } Genode::Entrypoint &entrypoint() override { return _env.ep(); }
void announce() override void announce() override
{ {
Genode::env()->parent()->announce(_ep.manage(*this)); _env.parent().announce(_env.ep().manage(*this));
} }
}; };
struct Main struct Block::Main
{ {
Genode::Env &env;
Genode::Heap heap { env.ram(), env.rm() };
Genode::Attached_rom_dataspace config { env, "config" };
Block::Root_multiple_clients root; Block::Root_multiple_clients root;
Main(Server::Entrypoint &ep) Main(Genode::Env &env)
: root(ep, Genode::env()->heap()) : env(env), root(env, heap, config.xml())
{ {
PINF("--- Starting AHCI driver -> done right .-) --\n"); Genode::log("--- Starting AHCI driver ---");
bool support_atapi = Genode::config()->xml_node().attribute_value("atapi", false); bool support_atapi = config.xml().attribute_value("atapi", false);
Ahci_driver::init(root, support_atapi); Ahci_driver::init(env, heap, root, support_atapi);
} }
}; };
namespace Server { namespace Component {
char const *name() { return "ahci_ep"; } Genode::size_t stack_size() { return 2 * 1024 * sizeof(long); }
size_t stack_size() { return 2 * 1024 * sizeof(long); } void construct(Genode::Env &env) { static Block::Main server(env); }
void construct(Entrypoint &ep) { static Main server(ep); }
} }

View File

@ -315,11 +315,14 @@ struct Sata_phy_ctrl : Attached_mmio
struct Exynos5_hba : Platform::Hba struct Exynos5_hba : Platform::Hba
{ {
Irq_connection irq { Board_base::SATA_IRQ }; Genode::Env &env;
Regulator::Connection clock_src { Regulator::CLK_SATA };
Regulator::Connection power_src { Regulator::PWR_SATA };
Exynos5_hba(Mmio::Delayer &delayer) Irq_connection irq { Board_base::SATA_IRQ };
Regulator::Connection clock_src { env, Regulator::CLK_SATA };
Regulator::Connection power_src { env, Regulator::PWR_SATA };
Exynos5_hba(Genode::Env &env, Mmio::Delayer &delayer)
: env(env)
{ {
clock_src.state(true); clock_src.state(true);
power_src.state(true); power_src.state(true);
@ -368,18 +371,18 @@ struct Exynos5_hba : Platform::Hba
Ram_dataspace_capability Ram_dataspace_capability
alloc_dma_buffer(size_t size) override alloc_dma_buffer(size_t size) override
{ {
return env()->ram_session()->alloc(size, UNCACHED); return env.ram().alloc(size, UNCACHED);
} }
void free_dma_buffer(Ram_dataspace_capability ds) void free_dma_buffer(Ram_dataspace_capability ds)
{ {
env()->ram_session()->free(ds); env.ram().free(ds);
} }
}; };
Platform::Hba &Platform::init(Mmio::Delayer &delayer) Platform::Hba &Platform::init(Genode::Env &env, Mmio::Delayer &delayer)
{ {
static Exynos5_hba h(delayer); static Exynos5_hba h(env, delayer);
return h; return h;
} }

View File

@ -32,19 +32,21 @@ struct X86_hba : Platform::Hba
PCI_CMD = 0x4, PCI_CMD = 0x4,
}; };
Platform::Connection pci; Genode::Env &env;
Platform::Connection pci { env };
Platform::Device_capability pci_device_cap; Platform::Device_capability pci_device_cap;
Lazy_volatile_object<Platform::Device_client> pci_device; Lazy_volatile_object<Platform::Device_client> pci_device;
Lazy_volatile_object<Irq_session_client> irq; Lazy_volatile_object<Irq_session_client> irq;
addr_t res_base; addr_t res_base;
size_t res_size; size_t res_size;
X86_hba() X86_hba(Genode::Env &env) : env(env)
{ {
pci_device_cap = retry<Platform::Session::Out_of_metadata>( pci_device_cap = retry<Platform::Session::Out_of_metadata>(
[&] () { return pci.next_device(pci_device_cap, AHCI_DEVICE, [&] () { return pci.next_device(pci_device_cap, AHCI_DEVICE,
CLASS_MASK); }, CLASS_MASK); },
[&] () { env()->parent()->upgrade(pci.cap(), "ram_quota=4096"); }); [&] () { env.parent().upgrade(pci.cap(), "ram_quota=4096"); });
if (!pci_device_cap.valid()) { if (!pci_device_cap.valid()) {
PERR("No AHCI controller found"); PERR("No AHCI controller found");
@ -105,7 +107,7 @@ struct X86_hba : Platform::Hba
char quota[32]; char quota[32];
Genode::snprintf(quota, sizeof(quota), "ram_quota=%zd", Genode::snprintf(quota, sizeof(quota), "ram_quota=%zd",
donate); donate);
Genode::env()->parent()->upgrade(pci.cap(), quota); env.parent().upgrade(pci.cap(), quota);
donate *= 2; donate *= 2;
}); });
} }
@ -136,7 +138,7 @@ struct X86_hba : Platform::Hba
[&] () { [&] () {
char quota[32]; char quota[32];
snprintf(quota, sizeof(quota), "ram_quota=%zd", donate); snprintf(quota, sizeof(quota), "ram_quota=%zd", donate);
env()->parent()->upgrade(pci.cap(), quota); env.parent().upgrade(pci.cap(), quota);
donate = donate * 2 > size ? 4096 : donate * 2; donate = donate * 2 > size ? 4096 : donate * 2;
}); });
} }
@ -148,8 +150,8 @@ struct X86_hba : Platform::Hba
}; };
Platform::Hba &Platform::init(Mmio::Delayer &) Platform::Hba &Platform::init(Genode::Env &env, Mmio::Delayer &)
{ {
static X86_hba h; static X86_hba h(env);
return h; return h;
} }

View File

@ -1,3 +1,4 @@
TARGET = ahci_drv TARGET = ahci_drv
SRC_CC = main.cc ahci.cc SRC_CC = main.cc ahci.cc
LIBS += server base config ahci_platform INC_DIR += $(PRG_DIR)
LIBS += base ahci_platform