From b93cb82d27c32c2ec9d3eafc04b70b6667fe8355 Mon Sep 17 00:00:00 2001 From: John Snow Date: Fri, 14 Nov 2014 22:07:32 +0100 Subject: [PATCH 44/48] ahci: Correct PIO/D2H FIS responses Message-id: <1416002855-4964-18-git-send-email-jsnow@redhat.com> Patchwork-id: 62403 O-Subject: [RHEV-7.1 qemu-kvm-rhev PATCH v2 17/20] ahci: Correct PIO/D2H FIS responses Bugzilla: 1024599 RH-Acked-by: Michael S. Tsirkin RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi Currently, the D2H FIS packets AHCI generates simply parrot back the LBA that the guest sent to us in the cmd_fis. However, some commands (like READ NATIVE MAX) modify the LBA registers as a return value, through which the AHCI D2H FIS is the only response mechanism. Thus, the D2H response should use the current register values, not the initial ones. This patch adjusts the LBA and drive select register responses for PIO Setup and D2H FIS response packets. Additionally, the PIO and D2H FIS responses copy too many bytes from the command FIS that it is being generated from. Specifically, byte 11 which is the Features(15:8) field for Register Host to Device FIS packets, is instead reserved for the PIO Setup FIS and should always be 0. Signed-off-by: John Snow Reviewed-by: Paolo Bonzini Tested-by: Michael S. Tsirkin Message-id: 1412204151-18117-2-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi (cherry picked from commit 7b8bad1b6abde7612940900dd1092dad873f1a11) Signed-off-by: John Snow Signed-off-by: Miroslav Rezanina --- hw/ide/ahci.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 2009973..ae4af45 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -599,6 +599,7 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len) uint8_t *pio_fis, *cmd_fis; uint64_t tbl_addr; dma_addr_t cmd_len = 0x80; + IDEState *s = &ad->port.ifs[0]; if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { return; @@ -628,21 +629,21 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len) pio_fis[0] = 0x5f; pio_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); - pio_fis[2] = ad->port.ifs[0].status; - pio_fis[3] = ad->port.ifs[0].error; - - pio_fis[4] = cmd_fis[4]; - pio_fis[5] = cmd_fis[5]; - pio_fis[6] = cmd_fis[6]; - pio_fis[7] = cmd_fis[7]; - pio_fis[8] = cmd_fis[8]; - pio_fis[9] = cmd_fis[9]; - pio_fis[10] = cmd_fis[10]; - pio_fis[11] = cmd_fis[11]; + pio_fis[2] = s->status; + pio_fis[3] = s->error; + + pio_fis[4] = s->sector; + pio_fis[5] = s->lcyl; + pio_fis[6] = s->hcyl; + pio_fis[7] = s->select; + pio_fis[8] = s->hob_sector; + pio_fis[9] = s->hob_lcyl; + pio_fis[10] = s->hob_hcyl; + pio_fis[11] = 0; pio_fis[12] = cmd_fis[12]; pio_fis[13] = cmd_fis[13]; pio_fis[14] = 0; - pio_fis[15] = ad->port.ifs[0].status; + pio_fis[15] = s->status; pio_fis[16] = len & 255; pio_fis[17] = len >> 8; pio_fis[18] = 0; @@ -669,6 +670,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) int i; dma_addr_t cmd_len = 0x80; int cmd_mapped = 0; + IDEState *s = &ad->port.ifs[0]; if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { return; @@ -686,17 +688,17 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) d2h_fis[0] = 0x34; d2h_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); - d2h_fis[2] = ad->port.ifs[0].status; - d2h_fis[3] = ad->port.ifs[0].error; - - d2h_fis[4] = cmd_fis[4]; - d2h_fis[5] = cmd_fis[5]; - d2h_fis[6] = cmd_fis[6]; - d2h_fis[7] = cmd_fis[7]; - d2h_fis[8] = cmd_fis[8]; - d2h_fis[9] = cmd_fis[9]; - d2h_fis[10] = cmd_fis[10]; - d2h_fis[11] = cmd_fis[11]; + d2h_fis[2] = s->status; + d2h_fis[3] = s->error; + + d2h_fis[4] = s->sector; + d2h_fis[5] = s->lcyl; + d2h_fis[6] = s->hcyl; + d2h_fis[7] = s->select; + d2h_fis[8] = s->hob_sector; + d2h_fis[9] = s->hob_lcyl; + d2h_fis[10] = s->hob_hcyl; + d2h_fis[11] = 0; d2h_fis[12] = cmd_fis[12]; d2h_fis[13] = cmd_fis[13]; for (i = 14; i < 20; i++) { -- 1.8.3.1