mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
parent
ecbb7534b9
commit
5366c8cf7e
@ -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)");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user