ahci: add sync operation support
- implemement 'flush cache ext' for ATA - enable sync operation for request stream issue #3636
This commit is contained in:
parent
e096202b1f
commit
5225d12381
|
@ -250,6 +250,13 @@ namespace Ahci {
|
||||||
write<Sector0_7::Tag>(slot);
|
write<Sector0_7::Tag>(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flush_cache_ext()
|
||||||
|
{
|
||||||
|
write<Bits::C>(1);
|
||||||
|
write<Device::Lba>(0);
|
||||||
|
write<Command>(0xea);
|
||||||
|
}
|
||||||
|
|
||||||
void atapi()
|
void atapi()
|
||||||
{
|
{
|
||||||
write<Bits::C>(1);
|
write<Bits::C>(1);
|
||||||
|
|
|
@ -171,10 +171,14 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||||
(pending_start >= block_number && pending_start <= end) ||
|
(pending_start >= block_number && pending_start <= end) ||
|
||||||
(pending_end >= block_number && pending_end <= end)) {
|
(pending_end >= block_number && pending_end <= end)) {
|
||||||
|
|
||||||
warning("overlap: "
|
warning("overlap: ",
|
||||||
"pending ", pending_start,
|
"pending ", pending_start,
|
||||||
" + ", req.operation.count, ", "
|
" + ", req.operation.count,
|
||||||
"request: ", block_number, " + ", request.operation.count);
|
" (", req.operation.type == Block::Operation::Type::WRITE ?
|
||||||
|
"write" : "read", "), ",
|
||||||
|
"request: ", block_number, " + ", request.operation.count,
|
||||||
|
" (", request.operation.type == Block::Operation::Type::WRITE ?
|
||||||
|
"write" : "read", ")");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,10 +252,14 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||||
|
|
||||||
void handle_irq(Port &port) override
|
void handle_irq(Port &port) override
|
||||||
{
|
{
|
||||||
|
unsigned is = port.read<Port::Is>();
|
||||||
|
|
||||||
/* ncg */
|
/* ncg */
|
||||||
if (_ncq_support(port))
|
if (_ncq_support(port) && Port::Is::Fpdma_irq::get(is))
|
||||||
while (Port::Is::Sdbs::get(port.read<Port::Is>()))
|
do {
|
||||||
port.ack_irq();
|
port.ack_irq();
|
||||||
|
}
|
||||||
|
while (Port::Is::Sdbs::get(port.read<Port::Is>()));
|
||||||
/* normal dma */
|
/* normal dma */
|
||||||
else if (Port::Is::Dma_ext_irq::get(port.read<Port::Is>()))
|
else if (Port::Is::Dma_ext_irq::get(port.read<Port::Is>()))
|
||||||
port.ack_irq();
|
port.ack_irq();
|
||||||
|
@ -272,14 +280,16 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||||
|
|
||||||
Response submit(Port &port, Block::Request const request) override
|
Response submit(Port &port, Block::Request const request) override
|
||||||
{
|
{
|
||||||
if (port.sanity_check(request) == false || port.dma_base == 0)
|
if (_writeable == false && request.operation.type == Block::Operation::Type::WRITE)
|
||||||
return Response::REJECTED;
|
return Response::REJECTED;
|
||||||
|
|
||||||
if (_writeable == false && request.operation.type == Block::Operation::Type::WRITE)
|
if (Block::Operation::has_payload(request.operation.type)) {
|
||||||
|
if (port.sanity_check(request) == false || port.dma_base == 0)
|
||||||
return Response::REJECTED;
|
return Response::REJECTED;
|
||||||
|
|
||||||
if (_overlap_check(request))
|
if (_overlap_check(request))
|
||||||
return Response::RETRY;
|
return Response::RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
Request *r = _slots.get();
|
Request *r = _slots.get();
|
||||||
|
|
||||||
|
@ -298,21 +308,26 @@ class Ata::Protocol : public Ahci::Protocol, Noncopyable
|
||||||
op.count * _block_size());
|
op.count * _block_size());
|
||||||
|
|
||||||
/* setup ATA command */
|
/* setup ATA command */
|
||||||
bool read = op.type == Block::Operation::Type::READ;
|
|
||||||
|
|
||||||
if (_ncq_support(port)) {
|
/* write bit for command header + read/write ATA requests */
|
||||||
table.fis.fpdma(read, op.block_number, op.count, slot);
|
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();
|
||||||
|
} 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' */
|
/* ensure that 'Cmd::St' is 1 before writing 'Sact' */
|
||||||
port.start();
|
port.start();
|
||||||
/* set pending */
|
/* set pending */
|
||||||
port.write<Port::Sact>(1U << slot);
|
port.write<Port::Sact>(1U << slot);
|
||||||
} else {
|
} else {
|
||||||
table.fis.dma_ext(read, op.block_number, op.count);
|
table.fis.dma_ext(write == false, op.block_number, op.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set or clear write flag in command header */
|
/* set or clear write flag in command header */
|
||||||
Command_header header(port.command_header_addr(slot));
|
Command_header header(port.command_header_addr(slot));
|
||||||
header.write<Command_header::Bits::W>(read ? 0 : 1);
|
header.write<Command_header::Bits::W>(write ? 1 : 0);
|
||||||
header.clear_byte_count();
|
header.clear_byte_count();
|
||||||
|
|
||||||
port.execute(slot);
|
port.execute(slot);
|
||||||
|
|
|
@ -148,8 +148,8 @@ class Atapi::Protocol : public Ahci::Protocol, Noncopyable
|
||||||
|
|
||||||
Response submit(Port &port, Block::Request const request) override
|
Response submit(Port &port, Block::Request const request) override
|
||||||
{
|
{
|
||||||
if (port.sanity_check(request) == false || port.dma_base == 0 ||
|
if (request.operation.type != Block::Operation::Type::READ ||
|
||||||
request.operation.type != Block::Operation::Type::READ)
|
port.sanity_check(request) == false || port.dma_base == 0)
|
||||||
return Response::REJECTED;
|
return Response::REJECTED;
|
||||||
|
|
||||||
if (_pending.operation.valid())
|
if (_pending.operation.valid())
|
||||||
|
|
|
@ -275,8 +275,9 @@ struct Ahci::Block_session_component : Rpc_object<Block::Session>,
|
||||||
|
|
||||||
Response response = Response::RETRY;
|
Response response = Response::RETRY;
|
||||||
|
|
||||||
/* only READ/WRITE requests, others are noops for now */
|
/* ignored operations */
|
||||||
if (Block::Operation::has_payload(request.operation.type) == false) {
|
if (request.operation.type == Block::Operation::Type::TRIM ||
|
||||||
|
request.operation.type == Block::Operation::Type::INVALID) {
|
||||||
request.success = true;
|
request.success = true;
|
||||||
progress = true;
|
progress = true;
|
||||||
return Response::REJECTED;
|
return Response::REJECTED;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user