ahci: do not copy port MMIO objects

Ref #2196
This commit is contained in:
Martin Stein 2017-03-06 12:45:27 +01:00 committed by Christian Helmuth
parent ecbb7534b9
commit 5366c8cf7e
4 changed files with 76 additions and 65 deletions

View File

@ -71,16 +71,6 @@ struct Ahci
scan_ports(env.rm(), env.ram());
}
bool atapi(unsigned sig)
{
return enable_atapi && (sig == ATAPI_SIG_QEMU || sig == ATAPI_SIG);
}
bool ata(unsigned sig)
{
return sig == ATA_SIG;
}
/**
* Forward IRQs to ports
*/
@ -115,8 +105,8 @@ struct Ahci
void scan_ports(Genode::Region_map &rm, Genode::Ram_session &ram)
{
Genode::log("number of ports: ", hba.port_count(), " "
"pi: ", Genode::Hex(hba.read<Hba::Pi>()));
log("number of ports: ", hba.port_count(), " pi: ",
Hex(hba.read<Hba::Pi>()));
unsigned available = hba.read<Hba::Pi>();
for (unsigned i = 0; i < hba.port_count(); i++) {
@ -125,42 +115,35 @@ struct Ahci
if (!(available & (1U << i)))
continue;
Port port(rm, hba, platform_hba, i);
/* check for ATA/ATAPI devices */
unsigned sig = port.read<Port::Sig>();
if (!atapi(sig) && !ata(sig)) {
Genode::log("\t\t#", i, ": off");
continue;
}
port.reset();
bool enabled = false;
try { enabled = port.enable(); }
catch (Port::Not_ready) { Genode::error("could not enable port ", i); }
Genode::log("\t\t#", i, ": ", atapi(sig) ? "ATAPI" : "ATA");
if (!enabled)
continue;
switch (sig) {
switch (Port_base(i, hba).read<Port_base::Sig>()) {
case ATA_SIG:
ports[i] = new (&alloc) Ata_driver(alloc, port, ram, root,
ready_count);
try {
ports[i] = new (&alloc)
Ata_driver(alloc, ram, root, ready_count, rm, hba,
platform_hba, i);
enabled = true;
} catch (...) { }
log("\t\t#", i, ":", enabled ? " ATA" : " off (ATA)");
break;
case ATAPI_SIG:
case ATAPI_SIG_QEMU:
ports[i] = new (&alloc) Atapi_driver(port, ram, root,
ready_count);
if (enable_atapi)
try {
ports[i] = new (&alloc)
Atapi_driver(ram, root, ready_count, rm, hba,
platform_hba, i);
enabled = true;
} catch (...) { }
log("\t\t#", i, ":", enabled ? " ATAPI" : " off (ATAPI)");
break;
default:
Genode::warning("device signature ", Genode::Hex(sig), " unsupported");
log("\t\t#", i, ": off (unknown device signature)");
}
}
};

View File

@ -388,18 +388,35 @@ struct Command_table
};
/**
* Minimalistic AHCI port structure to merely detect device signature
*/
struct Port_base : Genode::Mmio
{
/**
* Port signature
*/
struct Sig : Register<0x24, 32> { };
static constexpr Genode::addr_t offset() { return 0x100; }
static constexpr Genode::size_t size() { return 0x80; }
Port_base(unsigned number, Hba &hba)
: Mmio(hba.base + offset() + (number * size())) { }
};
/**
* AHCI port
*/
struct Port : Genode::Mmio
struct Port : Port_base
{
struct Not_ready : Genode::Exception { };
Genode::Region_map &rm;
Hba &hba;
Platform::Hba &platform_hba;
unsigned cmd_slots = hba.command_slots();
Hba &hba;
Platform::Hba &platform_hba;
unsigned cmd_slots = hba.command_slots();
Genode::Ram_dataspace_capability device_ds;
Genode::Ram_dataspace_capability cmd_ds;
@ -423,12 +440,14 @@ struct Port : Genode::Mmio
Port(Genode::Region_map &rm, Hba &hba, Platform::Hba &platform_hba,
unsigned number)
:
Mmio(hba.base + offset() + (number * size())),
rm(rm), hba(hba), platform_hba(platform_hba)
Port_base(number, hba), rm(rm), hba(hba),
platform_hba(platform_hba)
{
reset();
if (!enable())
throw 1;
stop();
if (!wait_for<Cmd::Cr>(0, hba.delayer(), 500, 1000))
Genode::error("failed to stop command list processing");
wait_for(hba.delayer(), Cmd::Cr::Equal(0));
}
virtual ~Port()
@ -449,9 +468,6 @@ struct Port : Genode::Mmio
}
}
static constexpr Genode::addr_t offset() { return 0x100; }
static constexpr Genode::size_t size() { return 0x80; }
/**
* Command list base (1K length naturally aligned)
*/
@ -612,11 +628,6 @@ struct Port : Genode::Mmio
struct Sts_bsy : Bitfield<7, 1> { }; /* interface is busy */
};
/**
* Port signature
*/
struct Sig : Register<0x24, 32> { };
/**
* Serial ATA status
*/
@ -797,10 +808,15 @@ struct Port_driver : Port, Block::Driver
Ahci_root &root;
unsigned &sem;
Port_driver(Port &port, Genode::Ram_session &ram, Ahci_root &root,
unsigned &sem)
: Port(port), Block::Driver(ram),
root(root), sem(sem) { sem++; }
Port_driver(Genode::Ram_session &ram,
Ahci_root &root,
unsigned &sem,
Genode::Region_map &rm,
Hba &hba,
Platform::Hba &platform_hba,
unsigned number)
: Port(rm, hba, platform_hba, number), Block::Driver(ram), root(root),
sem(sem) { sem++; }
virtual void handle_irq() = 0;

View File

@ -188,10 +188,16 @@ struct Ata_driver : Port_driver
Io_command *io_cmd = nullptr;
Block::Packet_descriptor pending[32];
Ata_driver(Genode::Allocator &alloc,
Port &port, Genode::Ram_session &ram,
Ahci_root &root, unsigned &sem)
: Port_driver(port, ram, root, sem), alloc(alloc)
Ata_driver(Genode::Allocator &alloc,
Genode::Ram_session &ram,
Ahci_root &root,
unsigned &sem,
Genode::Region_map &rm,
Hba &hba,
Platform::Hba &platform_hba,
unsigned number)
: Port_driver(ram, root, sem, rm, hba, platform_hba, number),
alloc(alloc)
{
Port::init();
identify_device();

View File

@ -24,8 +24,14 @@ struct Atapi_driver : Port_driver
unsigned sense_tries = 0;
Block::Packet_descriptor pending;
Atapi_driver(Port &port, Genode::Ram_session &ram, Ahci_root &root, unsigned &sem)
: Port_driver(port, ram, root, sem)
Atapi_driver(Genode::Ram_session &ram,
Ahci_root &root,
unsigned &sem,
Genode::Region_map &rm,
Hba &hba,
Platform::Hba &platform_hba,
unsigned number)
: Port_driver(ram, root, sem, rm, hba, platform_hba, number)
{
Port::init();
Port::write<Cmd::Atapi>(1);