ahci: Reset port before access

Also throw error if wakup from power safe mode failes.

Fix #1776
This commit is contained in:
Sebastian Sumpf 2015-11-12 15:00:39 +01:00 committed by Christian Helmuth
parent 5f2d92f916
commit ab79b0d5e0
2 changed files with 33 additions and 8 deletions

View File

@ -71,6 +71,11 @@ struct Ahci
return sig == ATAPI_SIG_QEMU || sig == ATAPI_SIG; return sig == ATAPI_SIG_QEMU || sig == ATAPI_SIG;
} }
bool is_ata(unsigned sig)
{
return sig == ATA_SIG;
}
/** /**
* Forward IRQs to ports * Forward IRQs to ports
*/ */
@ -121,12 +126,21 @@ struct Ahci
continue; continue;
Port port(hba, platform_hba, i); Port port(hba, platform_hba, i);
bool enabled = port.enable();
unsigned sig = port.read<Port::Sig>();
PINF("\t\t#%u: %s", i, enabled ? /* check for ATA/ATAPI devices */
(is_atapi(sig) ? "ATAPI" : "ATA") : unsigned sig = port.read<Port::Sig>();
"off"); if (!is_atapi(sig) && !is_ata(sig)) {
PINF("\t\t#%u: off", i);
continue;
}
port.reset();
bool enabled = false;
try { enabled = port.enable(); }
catch (Port::Not_ready) { PERR("Could not enable port %u", i); }
PINF("\t\t#%u: %s", i, is_atapi(sig) ? "ATAPI" : "ATA");
if (!enabled) if (!enabled)
continue; continue;

View File

@ -16,6 +16,7 @@
#include <block/component.h> #include <block/component.h>
#include <os/attached_mmio.h> #include <os/attached_mmio.h>
#include <util/retry.h>
#include <util/volatile_object.h> #include <util/volatile_object.h>
static bool constexpr verbose = false; static bool constexpr verbose = false;
@ -389,6 +390,9 @@ struct Command_table
*/ */
struct Port : Genode::Mmio struct Port : Genode::Mmio
{ {
struct Not_ready : Genode::Exception { };
Hba &hba; Hba &hba;
Platform::Hba &platform_hba; Platform::Hba &platform_hba;
unsigned cmd_slots = hba.command_slots(); unsigned cmd_slots = hba.command_slots();
@ -639,9 +643,16 @@ struct Port : Genode::Mmio
/* try to wake up device */ /* try to wake up device */
write<Cmd::Icc>(Ssts::Ipm::ACTIVE); write<Cmd::Icc>(Ssts::Ipm::ACTIVE);
while ((Ssts::Dec::get(status) != Ssts::Dec::ESTABLISHED) || Genode::retry<Not_ready>(
!(Ssts::Ipm::get(status) & Ssts::Ipm::ACTIVE)) [&] {
status = read<Ssts>(); if ((Ssts::Dec::get(status) != Ssts::Dec::ESTABLISHED) ||
!(Ssts::Ipm::get(status) & Ssts::Ipm::ACTIVE))
throw Not_ready();
},
[&] {
hba.delayer().usleep(1000);
status = read<Ssts>();
}, 10);
} }
return ((Ssts::Dec::get(status) == Ssts::Dec::ESTABLISHED) && return ((Ssts::Dec::get(status) == Ssts::Dec::ESTABLISHED) &&