2015-03-25 11:12:52 +01:00
|
|
|
/**
|
|
|
|
* \brief AHCI port controller handling
|
|
|
|
* \author Sebastian Sumpf
|
|
|
|
* \date 2015-04-29
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-01-16 15:33:56 +01:00
|
|
|
* Copyright (C) 2015-2017 Genode Labs GmbH
|
2015-03-25 11:12:52 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2017-02-11 15:16:12 +01:00
|
|
|
/* Genode includes */
|
|
|
|
#include <timer_session/connection.h>
|
2015-03-25 11:12:52 +01:00
|
|
|
|
2017-02-11 15:16:12 +01:00
|
|
|
/* local includes */
|
|
|
|
#include <ata_driver.h>
|
|
|
|
#include <atapi_driver.h>
|
2015-03-25 11:12:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
struct Ahci
|
|
|
|
{
|
2016-05-29 09:50:14 +02:00
|
|
|
Genode::Env &env;
|
|
|
|
Genode::Allocator &alloc;
|
|
|
|
|
2015-03-25 11:12:52 +01:00
|
|
|
/* read device signature */
|
|
|
|
enum Signature {
|
|
|
|
ATA_SIG = 0x101,
|
|
|
|
ATAPI_SIG = 0xeb140101,
|
|
|
|
ATAPI_SIG_QEMU = 0xeb140000, /* will be fixed in Qemu */
|
|
|
|
};
|
|
|
|
|
2017-02-11 15:16:12 +01:00
|
|
|
struct Timer_delayer : Mmio::Delayer, Timer::Connection
|
|
|
|
{
|
|
|
|
Timer_delayer(Genode::Env &env)
|
|
|
|
: Timer::Connection(env) { }
|
|
|
|
|
|
|
|
void usleep(unsigned us) { Timer::Connection::usleep(us); }
|
|
|
|
} _delayer { env };
|
|
|
|
|
2015-03-25 11:12:52 +01:00
|
|
|
Ahci_root &root;
|
2017-02-11 15:16:12 +01:00
|
|
|
Platform::Hba &platform_hba = Platform::init(env, _delayer);
|
|
|
|
Hba hba { env, platform_hba, _delayer };
|
2015-03-25 11:12:52 +01:00
|
|
|
|
|
|
|
enum { MAX_PORTS = 32 };
|
|
|
|
Port_driver *ports[MAX_PORTS];
|
|
|
|
bool port_claimed[MAX_PORTS];
|
|
|
|
|
2016-08-12 15:10:50 +02:00
|
|
|
Signal_handler<Ahci> irq;
|
|
|
|
unsigned ready_count = 0;
|
|
|
|
bool enable_atapi;
|
2015-03-25 11:12:52 +01:00
|
|
|
|
2016-05-29 09:50:14 +02:00
|
|
|
Ahci(Genode::Env &env, Genode::Allocator &alloc,
|
|
|
|
Ahci_root &root, bool support_atapi)
|
|
|
|
:
|
|
|
|
env(env), alloc(alloc),
|
|
|
|
root(root), irq(root.entrypoint(), *this, &Ahci::handle_irq),
|
|
|
|
enable_atapi(support_atapi)
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
|
|
|
info();
|
|
|
|
|
|
|
|
/* register irq handler */
|
|
|
|
platform_hba.sigh_irq(irq);
|
|
|
|
|
|
|
|
/* initialize HBA (IRQs, memory) */
|
|
|
|
hba.init();
|
|
|
|
|
|
|
|
/* search for devices */
|
2017-01-16 15:33:56 +01:00
|
|
|
scan_ports(env.rm(), env.ram());
|
2015-03-25 11:12:52 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
bool atapi(unsigned sig)
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
2016-05-24 09:54:03 +02:00
|
|
|
return enable_atapi && (sig == ATAPI_SIG_QEMU || sig == ATAPI_SIG);
|
2015-03-25 11:12:52 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
bool ata(unsigned sig)
|
2015-11-12 15:00:39 +01:00
|
|
|
{
|
|
|
|
return sig == ATA_SIG;
|
|
|
|
}
|
|
|
|
|
2015-03-25 11:12:52 +01:00
|
|
|
/**
|
|
|
|
* Forward IRQs to ports
|
|
|
|
*/
|
2016-08-12 15:10:50 +02:00
|
|
|
void handle_irq()
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
|
|
|
unsigned port_list = hba.read<Hba::Is>();
|
|
|
|
while (port_list) {
|
|
|
|
unsigned port = log2(port_list);
|
|
|
|
port_list &= ~(1U << port);
|
|
|
|
|
|
|
|
ports[port]->handle_irq();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clear status register */
|
|
|
|
hba.ack_irq();
|
|
|
|
|
|
|
|
/* ack at interrupt controller */
|
|
|
|
platform_hba.ack_irq();
|
|
|
|
}
|
|
|
|
|
|
|
|
void info()
|
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
using Genode::log;
|
|
|
|
|
|
|
|
log("version: "
|
|
|
|
"major=", Genode::Hex(hba.read<Hba::Version::Major>()), " "
|
|
|
|
"minor=", Genode::Hex(hba.read<Hba::Version::Minor>()));
|
|
|
|
log("command slots: ", hba.command_slots());
|
|
|
|
log("native command queuing: ", hba.ncq() ? "yes" : "no");
|
|
|
|
log("64-bit support: ", hba.supports_64bit() ? "yes" : "no");
|
2015-03-25 11:12:52 +01:00
|
|
|
}
|
|
|
|
|
2017-01-16 15:33:56 +01:00
|
|
|
void scan_ports(Genode::Region_map &rm, Genode::Ram_session &ram)
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::log("number of ports: ", hba.port_count(), " "
|
|
|
|
"pi: ", Genode::Hex(hba.read<Hba::Pi>()));
|
|
|
|
|
2015-10-06 15:36:34 +02:00
|
|
|
unsigned available = hba.read<Hba::Pi>();
|
2015-03-25 11:12:52 +01:00
|
|
|
for (unsigned i = 0; i < hba.port_count(); i++) {
|
|
|
|
|
|
|
|
/* check if port is implemented */
|
2015-10-06 15:36:34 +02:00
|
|
|
if (!(available & (1U << i)))
|
2015-03-25 11:12:52 +01:00
|
|
|
continue;
|
|
|
|
|
2016-05-29 09:50:14 +02:00
|
|
|
Port port(rm, hba, platform_hba, i);
|
2015-11-12 15:00:39 +01:00
|
|
|
|
|
|
|
/* check for ATA/ATAPI devices */
|
2015-03-25 11:12:52 +01:00
|
|
|
unsigned sig = port.read<Port::Sig>();
|
2016-05-11 18:21:47 +02:00
|
|
|
if (!atapi(sig) && !ata(sig)) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::log("\t\t#", i, ": off");
|
2015-11-12 15:00:39 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
port.reset();
|
|
|
|
|
|
|
|
bool enabled = false;
|
|
|
|
try { enabled = port.enable(); }
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
catch (Port::Not_ready) { Genode::error("could not enable port ", i); }
|
2015-03-25 11:12:52 +01:00
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::log("\t\t#", i, ": ", atapi(sig) ? "ATAPI" : "ATA");
|
2015-03-25 11:12:52 +01:00
|
|
|
|
|
|
|
if (!enabled)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
switch (sig) {
|
|
|
|
|
|
|
|
case ATA_SIG:
|
2017-01-16 15:33:56 +01:00
|
|
|
ports[i] = new (&alloc) Ata_driver(alloc, port, ram, root,
|
2016-08-12 15:10:50 +02:00
|
|
|
ready_count);
|
2015-03-25 11:12:52 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ATAPI_SIG:
|
|
|
|
case ATAPI_SIG_QEMU:
|
2017-01-16 15:33:56 +01:00
|
|
|
ports[i] = new (&alloc) Atapi_driver(port, ram, root,
|
2016-08-12 15:10:50 +02:00
|
|
|
ready_count);
|
2015-03-25 11:12:52 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::warning("device signature ", Genode::Hex(sig), " unsupported");
|
2015-03-25 11:12:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Block::Driver *claim_port(unsigned port_num)
|
|
|
|
{
|
2016-05-11 18:21:47 +02:00
|
|
|
if (!avail(port_num))
|
2015-03-25 11:12:52 +01:00
|
|
|
throw -1;
|
|
|
|
|
|
|
|
port_claimed[port_num] = true;
|
|
|
|
return ports[port_num];
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_port(unsigned port_num)
|
|
|
|
{
|
|
|
|
port_claimed[port_num] = false;
|
|
|
|
}
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
bool avail(unsigned port_num)
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
|
|
|
return port_num < MAX_PORTS && ports[port_num] && !port_claimed[port_num] &&
|
|
|
|
ports[port_num]->ready();
|
|
|
|
}
|
2016-02-11 20:03:38 +01:00
|
|
|
|
|
|
|
long device_number(const char *model_num, const char *serial_num)
|
|
|
|
{
|
|
|
|
for (long port_num = 0; port_num < MAX_PORTS; port_num++) {
|
|
|
|
Ata_driver* drv = dynamic_cast<Ata_driver *>(ports[port_num]);
|
|
|
|
if (!drv)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*drv->model == model_num && *drv->serial == serial_num)
|
|
|
|
return port_num;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2015-03-25 11:12:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static Ahci *sata_ahci(Ahci *ahci = 0)
|
|
|
|
{
|
|
|
|
static Ahci *a = ahci;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-29 09:50:14 +02:00
|
|
|
void Ahci_driver::init(Genode::Env &env, Genode::Allocator &alloc,
|
|
|
|
Ahci_root &root, bool support_atapi)
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
2016-05-29 09:50:14 +02:00
|
|
|
static Ahci ahci(env, alloc, root, support_atapi);
|
2015-03-25 11:12:52 +01:00
|
|
|
sata_ahci(&ahci);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Block::Driver *Ahci_driver::claim_port(long device_num)
|
|
|
|
{
|
|
|
|
return sata_ahci()->claim_port(device_num);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Ahci_driver::free_port(long device_num)
|
|
|
|
{
|
|
|
|
sata_ahci()->free_port(device_num);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
bool Ahci_driver::avail(long device_num)
|
2015-03-25 11:12:52 +01:00
|
|
|
{
|
2016-05-11 18:21:47 +02:00
|
|
|
return sata_ahci()->avail(device_num);
|
2015-03-25 11:12:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-11 20:03:38 +01:00
|
|
|
long Ahci_driver::device_number(char const *model_num, char const *serial_num)
|
|
|
|
{
|
|
|
|
return sata_ahci()->device_number(model_num, serial_num);
|
|
|
|
}
|