diff --git a/repos/os/src/drivers/ahci/ahci.cc b/repos/os/src/drivers/ahci/ahci.cc index b758362ef3..ccca61108c 100644 --- a/repos/os/src/drivers/ahci/ahci.cc +++ b/repos/os/src/drivers/ahci/ahci.cc @@ -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())); + log("number of ports: ", hba.port_count(), " pi: ", + Hex(hba.read())); unsigned available = hba.read(); 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(); - 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()) { 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)"); } } }; diff --git a/repos/os/src/drivers/ahci/ahci.h b/repos/os/src/drivers/ahci/ahci.h index 77eebd8074..e007ea0cea 100644 --- a/repos/os/src/drivers/ahci/ahci.h +++ b/repos/os/src/drivers/ahci/ahci.h @@ -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(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; diff --git a/repos/os/src/drivers/ahci/ata_driver.h b/repos/os/src/drivers/ahci/ata_driver.h index 4c713cd1de..e9d08e5a86 100644 --- a/repos/os/src/drivers/ahci/ata_driver.h +++ b/repos/os/src/drivers/ahci/ata_driver.h @@ -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(); diff --git a/repos/os/src/drivers/ahci/atapi_driver.h b/repos/os/src/drivers/ahci/atapi_driver.h index 39e541c33f..385a4e219e 100644 --- a/repos/os/src/drivers/ahci/atapi_driver.h +++ b/repos/os/src/drivers/ahci/atapi_driver.h @@ -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(1);