From 1374bec0634aac9a460fe3b57bbe8b1aa7a99cb7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:06 -0400 Subject: ide: simplify reset callbacks Drop the unused return value and make the callback optional. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 604152a823..273712faaa 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1147,11 +1147,6 @@ static void ahci_dma_restart_cb(void *opaque, int running, RunState state) { } -static int ahci_dma_reset(IDEDMA *dma) -{ - return 0; -} - static const IDEDMAOps ahci_dma_ops = { .start_dma = ahci_start_dma, .start_transfer = ahci_start_transfer, @@ -1162,7 +1157,6 @@ static const IDEDMAOps ahci_dma_ops = { .set_inactive = ahci_dma_set_inactive, .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, - .reset = ahci_dma_reset, }; void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) -- cgit v1.2.1 From 829b933b704a329d60d2ea1fe4c8e8e0a5505d8a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:07 -0400 Subject: ide: simplify set_inactive callbacks Drop the unused return value and make the callback optional. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 273712faaa..679357fc12 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1116,11 +1116,6 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) return 0; } -static int ahci_dma_set_inactive(IDEDMA *dma) -{ - return 0; -} - static int ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1154,7 +1149,6 @@ static const IDEDMAOps ahci_dma_ops = { .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, .add_status = ahci_dma_add_status, - .set_inactive = ahci_dma_set_inactive, .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, }; -- cgit v1.2.1 From c039cb1e5a7bf1f71fddbbe199eff7fbbfddb416 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:08 -0400 Subject: ide: simplify async_cmd_done callbacks Drop the unused return value. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 679357fc12..e494503330 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1116,7 +1116,7 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) return 0; } -static int ahci_async_cmd_done(IDEDMA *dma) +static void ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1130,8 +1130,6 @@ static int ahci_async_cmd_done(IDEDMA *dma) ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad); qemu_bh_schedule(ad->check_bh); } - - return 0; } static void ahci_irq_set(void *opaque, int n, int level) -- cgit v1.2.1 From 446351236b6e9c53b25e30d107c6235347df1dde Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:09 -0400 Subject: ide: simplify start_transfer callbacks Drop the unused return value and make the callback optional. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index e494503330..adbac3d52f 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -991,7 +991,7 @@ out: } /* DMA dev <-> ram */ -static int ahci_start_transfer(IDEDMA *dma) +static void ahci_start_transfer(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); IDEState *s = &ad->port.ifs[0]; @@ -1041,8 +1041,6 @@ out: /* done with DMA */ ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); } - - return 0; } static void ahci_start_dma(IDEDMA *dma, IDEState *s, -- cgit v1.2.1 From 0def37baf9add908c5462b0b8e2d3f80b563a9f9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:11 -0400 Subject: ide: remove wrong setting of BM_STATUS_INT Similar to the case removed in commit 69c38b8 (ide/core: Remove explicit setting of BM_STATUS_INT, 2011-05-19), the only remaining use of add_status(..., BM_STATUS_INT) is for short PRDs. The flag should not be raised in this case. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index adbac3d52f..14677ece97 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1107,10 +1107,6 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); DPRINTF(ad->port_no, "set status: %x\n", status); - if (status & BM_STATUS_INT) { - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); - } - return 0; } -- cgit v1.2.1 From 0e7ce54cf5fb9b7e8d19a5a4eb1facf123edbcef Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:12 -0400 Subject: ide: fold add_status callback into set_inactive It is now called only after the set_inactive callback. Put the two together. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 14677ece97..0ec5627a6c 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1102,14 +1102,6 @@ static int ahci_dma_set_unit(IDEDMA *dma, int unit) return 0; } -static int ahci_dma_add_status(IDEDMA *dma, int status) -{ - AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - DPRINTF(ad->port_no, "set status: %x\n", status); - - return 0; -} - static void ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -1140,7 +1132,6 @@ static const IDEDMAOps ahci_dma_ops = { .prepare_buf = ahci_dma_prepare_buf, .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, - .add_status = ahci_dma_add_status, .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, }; -- cgit v1.2.1 From 1f88f77348e14bd9f781db7ff66d2f680daa1d62 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:15 -0400 Subject: ahci: remove duplicate PORT_IRQ_* constants These are defined twice, just use one set consistently. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 0ec5627a6c..e1f27bda51 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -584,7 +584,7 @@ static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) s->dev[port].finished |= finished; *(uint32_t*)(sdb_fis + 4) = cpu_to_le32(s->dev[port].finished); - ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_STAT_SDBS); + ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_SDB_FIS); } static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) @@ -629,7 +629,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) } if (d2h_fis[2] & ERR_STAT) { - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_TFES); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR); } ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); @@ -1039,7 +1039,7 @@ out: if (!(s->status & DRQ_STAT)) { /* done with DMA */ - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); } } -- cgit v1.2.1 From c7e73adb48abb9fc5cbfc4f1ce6090fbdb0bdbea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:17 -0400 Subject: ide: make all commands go through cmd_done AHCI has code to fill in the D2H FIS trigger the IRQ all over the place. Centralize this in a single cmd_done callback by generalizing the existing async_cmd_done callback. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index e1f27bda51..b40ec06c3a 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -969,11 +969,6 @@ static int handle_cmd(AHCIState *s, int port, int slot) /* We're ready to process the command in FIS byte 2. */ ide_exec_cmd(&s->dev[port].port, cmd_fis[2]); - - if ((s->dev[port].port.ifs[0].status & (READY_STAT|DRQ_STAT|BUSY_STAT)) == - READY_STAT) { - ahci_write_fis_d2h(&s->dev[port], cmd_fis); - } } out: @@ -1036,11 +1031,6 @@ out: } s->end_transfer_func(s); - - if (!(s->status & DRQ_STAT)) { - /* done with DMA */ - ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); - } } static void ahci_start_dma(IDEDMA *dma, IDEState *s, @@ -1102,11 +1092,11 @@ static int ahci_dma_set_unit(IDEDMA *dma, int unit) return 0; } -static void ahci_async_cmd_done(IDEDMA *dma) +static void ahci_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - DPRINTF(ad->port_no, "async cmd done\n"); + DPRINTF(ad->port_no, "cmd done\n"); /* update d2h status */ ahci_write_fis_d2h(ad, NULL); @@ -1132,7 +1122,7 @@ static const IDEDMAOps ahci_dma_ops = { .prepare_buf = ahci_dma_prepare_buf, .rw_buf = ahci_dma_rw_buf, .set_unit = ahci_dma_set_unit, - .async_cmd_done = ahci_async_cmd_done, + .cmd_done = ahci_cmd_done, .restart_cb = ahci_dma_restart_cb, }; -- cgit v1.2.1 From 088415202b9dadb387cb6d9fd25324ae7fd4da4b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 4 Aug 2014 17:11:18 -0400 Subject: ahci: construct PIO Setup FIS for PIO commands PIO commands should put a PIO Setup FIS in the receive area when data transfer ends. Currently QEMU does not do this and only places the D2H FIS at the end of the operation. Signed-off-by: Paolo Bonzini Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi --- hw/ide/ahci.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'hw/ide/ahci.c') diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index b40ec06c3a..4cda0d0075 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -587,6 +587,71 @@ static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_SDB_FIS); } +static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len) +{ + AHCIPortRegs *pr = &ad->port_regs; + uint8_t *pio_fis, *cmd_fis; + uint64_t tbl_addr; + dma_addr_t cmd_len = 0x80; + + if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { + return; + } + + /* map cmd_fis */ + tbl_addr = le64_to_cpu(ad->cur_cmd->tbl_addr); + cmd_fis = dma_memory_map(ad->hba->as, tbl_addr, &cmd_len, + DMA_DIRECTION_TO_DEVICE); + + if (cmd_fis == NULL) { + DPRINTF(ad->port_no, "dma_memory_map failed in ahci_write_fis_pio"); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_HBUS_ERR); + return; + } + + if (cmd_len != 0x80) { + DPRINTF(ad->port_no, + "dma_memory_map mapped too few bytes in ahci_write_fis_pio"); + dma_memory_unmap(ad->hba->as, cmd_fis, cmd_len, + DMA_DIRECTION_TO_DEVICE, cmd_len); + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_HBUS_ERR); + return; + } + + pio_fis = &ad->res_fis[RES_FIS_PSFIS]; + + 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[12] = cmd_fis[12]; + pio_fis[13] = cmd_fis[13]; + pio_fis[14] = 0; + pio_fis[15] = ad->port.ifs[0].status; + pio_fis[16] = len & 255; + pio_fis[17] = len >> 8; + pio_fis[18] = 0; + pio_fis[19] = 0; + + if (pio_fis[2] & ERR_STAT) { + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_TF_ERR); + } + + ahci_trigger_irq(ad->hba, ad, PORT_IRQ_PIOS_FIS); + + dma_memory_unmap(ad->hba->as, cmd_fis, cmd_len, + DMA_DIRECTION_TO_DEVICE, cmd_len); +} + static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) { AHCIPortRegs *pr = &ad->port_regs; @@ -1031,6 +1096,11 @@ out: } 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.2.1