diff --git a/repos/os/src/drivers/ahci/ata_protocol.h b/repos/os/src/drivers/ahci/ata_protocol.h index adecb5537..e37098b68 100644 --- a/repos/os/src/drivers/ahci/ata_protocol.h +++ b/repos/os/src/drivers/ahci/ata_protocol.h @@ -124,6 +124,8 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable { private: + bool _syncing { false }; + struct Request : Block::Request { bool valid() const { return operation.valid(); } @@ -162,6 +164,9 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable block_number_t end = block_number + request.operation.count - 1; auto overlap_check = [&] (Request const &req) { + if (req.operation.type == Block::Operation::Type::SYNC) + return false; + block_number_t pending_start = req.operation.block_number; block_number_t pending_end = pending_start + req.operation.count - 1; @@ -266,6 +271,8 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable _slot_states = port.read() | port.read(); port.stop(); + + _syncing = false; } Block::Session::Info info() const override @@ -280,10 +287,18 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable Response submit(Port &port, Block::Request const request) override { - if (_writeable == false && request.operation.type == Block::Operation::Type::WRITE) + Block::Operation const op = request.operation; + + bool const sync = (op.type == Block::Operation::Type::SYNC); + bool const write = (op.type == Block::Operation::Type::WRITE); + + if ((sync && _slot_states) || _syncing) + return Response::RETRY; + + if (_writeable == false && write) return Response::REJECTED; - if (Block::Operation::has_payload(request.operation.type)) { + if (Block::Operation::has_payload(op.type)) { if (port.sanity_check(request) == false || port.dma_base == 0) return Response::REJECTED; @@ -298,7 +313,6 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable *r = request; - Block::Operation op = request.operation; size_t slot = _slots.index(*r); _slot_states |= 1u << slot; @@ -308,13 +322,9 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable op.count * _block_size()); /* setup ATA command */ - - /* write bit for command header + read/write ATA requests */ - bool const write = (op.type == Block::Operation::Type::WRITE); - bool const sync = (op.type == Block::Operation::Type::SYNC); - if (sync) { table.fis.flush_cache_ext(); + _syncing = true; } else if (_ncq_support(port)) { table.fis.fpdma(write == false, op.block_number, op.count, slot); /* ensure that 'Cmd::St' is 1 before writing 'Sact' */