hw/ide/ahci: PxCI should not get cleared when ERR_STAT is set

For NCQ, PxCI is cleared on command queued successfully.
For non-NCQ, PxCI is cleared on command completed successfully.
Successfully means ERR_STAT, BUSY and DRQ are all cleared.

A command that has ERR_STAT set, does not get to clear PxCI.
See AHCI 1.3.1, section 5.3.8, states RegFIS:Entry and RegFIS:ClearCI,
and 5.3.16.5 ERR:FatalTaskfile.

In the case of non-NCQ commands, not clearing PxCI is needed in order
for host software to be able to see which command slot that failed.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Message-id: 20230609140844.202795-7-nks@flawful.org
Signed-off-by: John Snow <jsnow@redhat.com>
This commit is contained in:
Niklas Cassel 2023-06-09 16:08:42 +02:00 committed by John Snow
parent d73b84d0b6
commit 1a16ce64fd
3 changed files with 88 additions and 33 deletions

View file

@ -1523,7 +1523,8 @@ static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot)
{
IDEState *ide_state = &ad->port.ifs[0];
if (!(ide_state->status & (BUSY_STAT | DRQ_STAT))) {
if (!(ide_state->status & ERR_STAT) &&
!(ide_state->status & (BUSY_STAT | DRQ_STAT))) {
ad->port_regs.cmd_issue &= ~(1 << slot);
}
}
@ -1532,6 +1533,7 @@ static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot)
static void ahci_cmd_done(const IDEDMA *dma)
{
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
IDEState *ide_state = &ad->port.ifs[0];
trace_ahci_cmd_done(ad->hba, ad->port_no);
@ -1548,7 +1550,8 @@ static void ahci_cmd_done(const IDEDMA *dma)
*/
ahci_write_fis_d2h(ad, true);
if (ad->port_regs.cmd_issue && !ad->check_bh) {
if (!(ide_state->status & ERR_STAT) &&
ad->port_regs.cmd_issue && !ad->check_bh) {
ad->check_bh = qemu_bh_new_guarded(ahci_check_cmd_bh, ad,
&ad->mem_reentrancy_guard);
qemu_bh_schedule(ad->check_bh);