From 956556e131e35f387ac482ad7b41151576fef057 Mon Sep 17 00:00:00 2001 From: John Snow Date: Wed, 6 Jun 2018 15:09:50 -0400 Subject: ahci: move PIO Setup FIS before transfer, fix it for ATAPI commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PIO Setup FIS is written in the PIO:Entry state, which comes before the ATA and ATAPI data transfer states. As a result, the PIO Setup FIS interrupt is now raised before DMA ends for ATAPI commands, and tests have to be adjusted. This is also hinted by the description of the command header in the AHCI specification, where the "A" bit is described as When ‘1’, indicates that a PIO setup FIS shall be sent by the device indicating a transfer for the ATAPI command. and also by the description of the ACMD (ATAPI command region): The ATAPI command must be either 12 or 16 bytes in length. The length transmitted by the HBA is determined by the PIO setup FIS that is sent by the device requesting the ATAPI command. QEMU, which conflates the "generator" and the "receiver" of the FIS into one device, always uses ATAPI_PACKET_SIZE, aka 12, for the length. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Reviewed-by: Philippe Mathieu-Daudé Message-id: 20180606190955.20845-3-jsnow@redhat.com Signed-off-by: John Snow --- hw/ide/ahci.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'hw/ide') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 571e32d..f25bef5 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, -- cgit v1.1