aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ide/ahci.c16
-rw-r--r--tests/libqos/ahci.c35
-rw-r--r--tests/libqos/ahci.h3
3 files changed, 27 insertions, 27 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 571e32dd66..f25bef501d 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1259,7 +1259,6 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
g_free(pretty_fis);
}
s->dev[port].done_atapi_packet = false;
- /* XXX send PIO setup FIS */
}
ide_state->error = 0;
@@ -1353,10 +1352,12 @@ static void ahci_start_transfer(IDEDMA *dma)
int is_atapi = opts & AHCI_CMD_ATAPI;
int has_sglist = 0;
+ /* PIO FIS gets written prior to transfer */
+ ahci_write_fis_pio(ad, size);
+
if (is_atapi && !ad->done_atapi_packet) {
/* already prepopulated iobuffer */
ad->done_atapi_packet = true;
- size = 0;
goto out;
}
@@ -1376,19 +1377,12 @@ static void ahci_start_transfer(IDEDMA *dma)
}
}
+ /* Update number of transferred bytes, destroy sglist */
+ dma_buf_commit(s, size);
out:
/* declare that we processed everything */
s->data_ptr = s->data_end;
-
- /* Update number of transferred bytes, destroy sglist */
- dma_buf_commit(s, size);
-
s->end_transfer_func(s);
-
- if (!(s->status & DRQ_STAT)) {
- /* done with PIO send/receive */
- ahci_write_fis_pio(ad, le32_to_cpu(ad->cur_cmd->status));
- }
}
static void ahci_start_dma(IDEDMA *dma, IDEState *s,
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index 63e1f9b92d..7264e085d0 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -478,10 +478,10 @@ void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot)
g_free(d2h);
}
-void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t port,
- uint8_t slot, size_t buffsize)
+void ahci_port_check_pio_sanity(AHCIQState *ahci, AHCICommand *cmd)
{
PIOSetupFIS *pio = g_malloc0(0x20);
+ uint8_t port = cmd->port;
/* We cannot check the Status or E_Status registers, because
* the status may have again changed between the PIO Setup FIS
@@ -489,15 +489,22 @@ void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t port,
qtest_memread(ahci->parent->qts, ahci->port[port].fb + 0x20, pio, 0x20);
g_assert_cmphex(pio->fis_type, ==, 0x5f);
- /* BUG: PIO Setup FIS as utilized by QEMU tries to fit the entire
- * transfer size in a uint16_t field. The maximum transfer size can
- * eclipse this; the field is meant to convey the size of data per
- * each Data FIS, not the entire operation as a whole. For now,
- * we will sanity check the broken case where applicable. */
- if (buffsize <= UINT16_MAX) {
- g_assert_cmphex(le16_to_cpu(pio->tx_count), ==, buffsize);
+ /* Data transferred by PIO will either be:
+ * (1) 12 or 16 bytes for an ATAPI command packet (QEMU always uses 12), or
+ * (2) Actual data from the drive.
+ * If we do both, (2) winds up erasing any evidence of (1).
+ */
+ if (cmd->props->atapi && (cmd->xbytes == 0 || cmd->props->dma)) {
+ g_assert(le16_to_cpu(pio->tx_count) == 12 ||
+ le16_to_cpu(pio->tx_count) == 16);
+ } else {
+ /* The AHCI test suite here does not test any PIO command that specifies
+ * a DRQ block larger than one sector (like 0xC4), so this should always
+ * be one sector or less. */
+ size_t pio_len = ((cmd->xbytes % cmd->sector_size) ?
+ (cmd->xbytes % cmd->sector_size) : cmd->sector_size);
+ g_assert_cmphex(le16_to_cpu(pio->tx_count), ==, pio_len);
}
-
g_free(pio);
}
@@ -832,9 +839,9 @@ void ahci_command_enable_atapi_dma(AHCICommand *cmd)
RegH2DFIS *fis = &(cmd->fis);
g_assert(cmd->props->atapi);
fis->feature_low |= 0x01;
- cmd->interrupts &= ~AHCI_PX_IS_PSS;
+ /* PIO is still used to transfer the ATAPI command */
+ g_assert(cmd->props->pio);
cmd->props->dma = true;
- cmd->props->pio = false;
/* BUG: We expect the DMA Setup interrupt for DMA commands */
/* cmd->interrupts |= AHCI_PX_IS_DSS; */
}
@@ -846,7 +853,7 @@ AHCICommand *ahci_command_create(uint8_t command_name)
g_assert(props);
cmd = g_new0(AHCICommand, 1);
- g_assert(!(props->dma && props->pio));
+ g_assert(!(props->dma && props->pio) || props->atapi);
g_assert(!(props->lba28 && props->lba48));
g_assert(!(props->read && props->write));
g_assert(!props->size || props->data);
@@ -1218,7 +1225,7 @@ void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd)
ahci_port_check_d2h_sanity(ahci, port, slot);
}
if (cmd->props->pio) {
- ahci_port_check_pio_sanity(ahci, port, slot, cmd->xbytes);
+ ahci_port_check_pio_sanity(ahci, cmd);
}
}
diff --git a/tests/libqos/ahci.h b/tests/libqos/ahci.h
index 715ca1e226..13f6d87b75 100644
--- a/tests/libqos/ahci.h
+++ b/tests/libqos/ahci.h
@@ -596,8 +596,7 @@ void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port,
uint32_t intr_mask);
void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot);
void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot);
-void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t port,
- uint8_t slot, size_t buffsize);
+void ahci_port_check_pio_sanity(AHCIQState *ahci, AHCICommand *cmd);
void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd);
/* Misc */