summaryrefslogtreecommitdiffstats
path: root/hw/ide/atapi.c
diff options
context:
space:
mode:
authorPeter Maydell2018-06-11 12:12:46 +0200
committerPeter Maydell2018-06-11 12:12:46 +0200
commita7a7309ca52c327c6603d60db90ae4feeae719f7 (patch)
tree6951a90343b7720974921c64b48dc157f24dd98b /hw/ide/atapi.c
parentMerge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180608'... (diff)
parentide: introduce ide_transfer_start_norecurse (diff)
downloadqemu-a7a7309ca52c327c6603d60db90ae4feeae719f7.tar.gz
qemu-a7a7309ca52c327c6603d60db90ae4feeae719f7.tar.xz
qemu-a7a7309ca52c327c6603d60db90ae4feeae719f7.zip
Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging
Pull request # gpg: Signature made Fri 08 Jun 2018 18:46:24 BST # gpg: using RSA key 7DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * remotes/jnsnow/tags/ide-pull-request: (30 commits) ide: introduce ide_transfer_start_norecurse atapi: call ide_set_irq before ide_transfer_start ide: make ide_transfer_stop idempotent ide: call ide_cmd_done from ide_transfer_stop ide: push end_transfer_func out of start_transfer callback, rename callback ahci: move PIO Setup FIS before transfer, fix it for ATAPI commands libqos/ahci: track sector size MAINTAINERS: Add the cdrom-test to John's section tests/cdrom-test: Test that -cdrom parameter is working tests/cdrom-test: Test booting from CD-ROM ISO image file tests/boot-sector: Add magic bytes to s390x boot code header ahci: make ahci_mem_write traces more descriptive ahci: delete old host register address definitions ahci: adjust ahci_mem_write to work on registers ahci: fix spacing damage on ahci_mem_write ahci: make mem_read_32 traces more descriptive ahci: modify ahci_mem_read_32 to work on register numbers ahci: fix host register max address ahci: add host register enumeration ahci: delete old port register address definitions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/ide/atapi.c')
-rw-r--r--hw/ide/atapi.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index c0509c8bf5..39e473f9c2 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -245,15 +245,11 @@ static uint16_t atapi_byte_count_limit(IDEState *s)
void ide_atapi_cmd_reply_end(IDEState *s)
{
int byte_count_limit, size, ret;
- trace_ide_atapi_cmd_reply_end(s, s->packet_transfer_size,
- s->elementary_transfer_size,
- s->io_buffer_index);
- if (s->packet_transfer_size <= 0) {
- /* end of transfer */
- ide_atapi_cmd_ok(s);
- ide_set_irq(s->bus);
- trace_ide_atapi_cmd_reply_end_eot(s, s->status);
- } else {
+ while (s->packet_transfer_size > 0) {
+ trace_ide_atapi_cmd_reply_end(s, s->packet_transfer_size,
+ s->elementary_transfer_size,
+ s->io_buffer_index);
+
/* see if a new sector must be read */
if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
if (!s->elementary_transfer_size) {
@@ -279,14 +275,10 @@ void ide_atapi_cmd_reply_end(IDEState *s)
size = s->cd_sector_size - s->io_buffer_index;
if (size > s->elementary_transfer_size)
size = s->elementary_transfer_size;
- s->packet_transfer_size -= size;
- s->elementary_transfer_size -= size;
- s->io_buffer_index += size;
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
- size, ide_atapi_cmd_reply_end);
} else {
/* a new transfer is needed */
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
+ ide_set_irq(s->bus);
byte_count_limit = atapi_byte_count_limit(s);
trace_ide_atapi_cmd_reply_end_bcl(s, byte_count_limit);
size = s->packet_transfer_size;
@@ -304,15 +296,27 @@ void ide_atapi_cmd_reply_end(IDEState *s)
if (size > (s->cd_sector_size - s->io_buffer_index))
size = (s->cd_sector_size - s->io_buffer_index);
}
- s->packet_transfer_size -= size;
- s->elementary_transfer_size -= size;
- s->io_buffer_index += size;
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
- size, ide_atapi_cmd_reply_end);
- ide_set_irq(s->bus);
trace_ide_atapi_cmd_reply_end_new(s, s->status);
}
+ s->packet_transfer_size -= size;
+ s->elementary_transfer_size -= size;
+ s->io_buffer_index += size;
+
+ /* Some adapters process PIO data right away. In that case, we need
+ * to avoid mutual recursion between ide_transfer_start
+ * and ide_atapi_cmd_reply_end.
+ */
+ if (!ide_transfer_start_norecurse(s,
+ s->io_buffer + s->io_buffer_index - size,
+ size, ide_atapi_cmd_reply_end)) {
+ return;
+ }
}
+
+ /* end of transfer */
+ trace_ide_atapi_cmd_reply_end_eot(s, s->status);
+ ide_atapi_cmd_ok(s);
+ ide_set_irq(s->bus);
}
/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */