* [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives
2016-01-19 4:51 [Qemu-devel] [PATCH 0/5] ide: fix atapi software reset John Snow
@ 2016-01-19 4:51 ` John Snow
2016-01-19 11:48 ` Paolo Bonzini
2016-01-19 4:51 ` [Qemu-devel] [PATCH 2/5] ide: code motion John Snow
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: John Snow @ 2016-01-19 4:51 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, John Snow, qemu-devel, stefanha
This command is meant for ATAPI devices only, prohibit acknowledging it with
a command aborted response when an IDE device is busy.
Signed-off-by: John Snow <jsnow@redhat.com>
---
hw/ide/core.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index da3baab..ba33064 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1876,9 +1876,12 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
return;
}
- /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */
- if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)
- return;
+ /* Only RESET is allowed to an ATAPI device while BSY and/or DRQ are set. */
+ if (s->status & (BUSY_STAT|DRQ_STAT)) {
+ if (!(val == WIN_DEVICE_RESET) && (s->drive_kind == IDE_CD)) {
+ return;
+ }
+ }
if (!ide_cmd_permitted(s, val)) {
ide_abort_command(s);
--
2.4.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives
2016-01-19 4:51 ` [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives John Snow
@ 2016-01-19 11:48 ` Paolo Bonzini
2016-01-19 17:04 ` John Snow
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2016-01-19 11:48 UTC (permalink / raw)
To: John Snow, qemu-block; +Cc: kwolf, qemu-devel, stefanha
On 19/01/2016 05:51, John Snow wrote:
> + /* Only RESET is allowed to an ATAPI device while BSY and/or DRQ are set. */
> + if (s->status & (BUSY_STAT|DRQ_STAT)) {
> + if (!(val == WIN_DEVICE_RESET) && (s->drive_kind == IDE_CD)) {
I was going to complain about Pascal-ish parentheses, but actually I
think there is a bug here; the expression just looks weird.
Did you mean
if (!(val == WIN_DEVICE_RESET && s->drive_kind == IDE_CD))
or equivalently applying de Morgan's law:
if (s->drive_kind != IDE_CD || val != WIN_DEVICE_RESET)
?
Paolo
> + return;
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives
2016-01-19 11:48 ` Paolo Bonzini
@ 2016-01-19 17:04 ` John Snow
2016-01-19 17:26 ` Laszlo Ersek
0 siblings, 1 reply; 10+ messages in thread
From: John Snow @ 2016-01-19 17:04 UTC (permalink / raw)
To: Paolo Bonzini, qemu-block; +Cc: kwolf, qemu-devel, stefanha
On 01/19/2016 06:48 AM, Paolo Bonzini wrote:
>
>
> On 19/01/2016 05:51, John Snow wrote:
>> + /* Only RESET is allowed to an ATAPI device while BSY and/or DRQ are set. */
>> + if (s->status & (BUSY_STAT|DRQ_STAT)) {
>> + if (!(val == WIN_DEVICE_RESET) && (s->drive_kind == IDE_CD)) {
>
> I was going to complain about Pascal-ish parentheses, but actually I
> think there is a bug here; the expression just looks weird.
>
> Did you mean
>
> if (!(val == WIN_DEVICE_RESET && s->drive_kind == IDE_CD))
>
> or equivalently applying de Morgan's law:
>
> if (s->drive_kind != IDE_CD || val != WIN_DEVICE_RESET)
>
> ?
>
> Paolo
>
>> + return;
>
ugh, yes, I typo'd. Thank you.
If you're still up, which do you find more readable?
The (!(A && B)) form or the (!A || !B) form?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives
2016-01-19 17:04 ` John Snow
@ 2016-01-19 17:26 ` Laszlo Ersek
0 siblings, 0 replies; 10+ messages in thread
From: Laszlo Ersek @ 2016-01-19 17:26 UTC (permalink / raw)
To: John Snow; +Cc: kwolf, Paolo Bonzini, stefanha, qemu-devel, qemu-block
On 01/19/16 18:04, John Snow wrote:
>
>
> On 01/19/2016 06:48 AM, Paolo Bonzini wrote:
>>
>>
>> On 19/01/2016 05:51, John Snow wrote:
>>> + /* Only RESET is allowed to an ATAPI device while BSY and/or DRQ are set. */
>>> + if (s->status & (BUSY_STAT|DRQ_STAT)) {
>>> + if (!(val == WIN_DEVICE_RESET) && (s->drive_kind == IDE_CD)) {
>>
>> I was going to complain about Pascal-ish parentheses, but actually I
>> think there is a bug here; the expression just looks weird.
>>
>> Did you mean
>>
>> if (!(val == WIN_DEVICE_RESET && s->drive_kind == IDE_CD))
>>
>> or equivalently applying de Morgan's law:
>>
>> if (s->drive_kind != IDE_CD || val != WIN_DEVICE_RESET)
>>
>> ?
>>
>> Paolo
>>
>>> + return;
>>
>
> ugh, yes, I typo'd. Thank you.
>
> If you're still up, which do you find more readable?
> The (!(A && B)) form or the (!A || !B) form?
You didn't ask me, but that's no problem for me. :)
The logical negation operator "!" has much-much stronger binding than
the logical "and" and logical "or" ones. If you use the first form,
!(A && B)
it works, but spacetime will curl every time someone sees those
parentheses overriding the nice n' tight binding of "!".
So, for me, only the second form *exists* -- for me, the operand of the
logical negation operator must always be as "indivisible" an expression
as possible :)
So,
(!A || !B)
without a doubt.
Thanks
Laszlo
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/5] ide: code motion
2016-01-19 4:51 [Qemu-devel] [PATCH 0/5] ide: fix atapi software reset John Snow
2016-01-19 4:51 ` [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives John Snow
@ 2016-01-19 4:51 ` John Snow
2016-01-19 4:51 ` [Qemu-devel] [PATCH 3/5] ide: move buffered DMA cancel to core John Snow
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: John Snow @ 2016-01-19 4:51 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, John Snow, qemu-devel, stefanha
Shuffle the reset function upwards.
Signed-off-by: John Snow <jsnow@redhat.com>
---
hw/ide/core.c | 116 +++++++++++++++++++++++++++++-----------------------------
1 file changed, 58 insertions(+), 58 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index ba33064..75486c2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1174,6 +1174,64 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
}
+static void ide_reset(IDEState *s)
+{
+#ifdef DEBUG_IDE
+ printf("ide: reset\n");
+#endif
+
+ if (s->pio_aiocb) {
+ blk_aio_cancel(s->pio_aiocb);
+ s->pio_aiocb = NULL;
+ }
+
+ if (s->drive_kind == IDE_CFATA)
+ s->mult_sectors = 0;
+ else
+ s->mult_sectors = MAX_MULT_SECTORS;
+ /* ide regs */
+ s->feature = 0;
+ s->error = 0;
+ s->nsector = 0;
+ s->sector = 0;
+ s->lcyl = 0;
+ s->hcyl = 0;
+
+ /* lba48 */
+ s->hob_feature = 0;
+ s->hob_sector = 0;
+ s->hob_nsector = 0;
+ s->hob_lcyl = 0;
+ s->hob_hcyl = 0;
+
+ s->select = 0xa0;
+ s->status = READY_STAT | SEEK_STAT;
+
+ s->lba48 = 0;
+
+ /* ATAPI specific */
+ s->sense_key = 0;
+ s->asc = 0;
+ s->cdrom_changed = 0;
+ s->packet_transfer_size = 0;
+ s->elementary_transfer_size = 0;
+ s->io_buffer_index = 0;
+ s->cd_sector_size = 0;
+ s->atapi_dma = 0;
+ s->tray_locked = 0;
+ s->tray_open = 0;
+ /* ATA DMA state */
+ s->io_buffer_size = 0;
+ s->req_nb_sectors = 0;
+
+ ide_set_signature(s);
+ /* init the transfer handler so that 0xffff is returned on data
+ accesses */
+ s->end_transfer_func = ide_dummy_transfer_stop;
+ ide_dummy_transfer_stop(s);
+ s->media_changed = 0;
+}
+
static bool cmd_nop(IDEState *s, uint8_t cmd)
{
return true;
@@ -2181,64 +2239,6 @@ static void ide_dummy_transfer_stop(IDEState *s)
s->io_buffer[3] = 0xff;
}
-static void ide_reset(IDEState *s)
-{
-#ifdef DEBUG_IDE
- printf("ide: reset\n");
-#endif
-
- if (s->pio_aiocb) {
- blk_aio_cancel(s->pio_aiocb);
- s->pio_aiocb = NULL;
- }
-
- if (s->drive_kind == IDE_CFATA)
- s->mult_sectors = 0;
- else
- s->mult_sectors = MAX_MULT_SECTORS;
- /* ide regs */
- s->feature = 0;
- s->error = 0;
- s->nsector = 0;
- s->sector = 0;
- s->lcyl = 0;
- s->hcyl = 0;
-
- /* lba48 */
- s->hob_feature = 0;
- s->hob_sector = 0;
- s->hob_nsector = 0;
- s->hob_lcyl = 0;
- s->hob_hcyl = 0;
-
- s->select = 0xa0;
- s->status = READY_STAT | SEEK_STAT;
-
- s->lba48 = 0;
-
- /* ATAPI specific */
- s->sense_key = 0;
- s->asc = 0;
- s->cdrom_changed = 0;
- s->packet_transfer_size = 0;
- s->elementary_transfer_size = 0;
- s->io_buffer_index = 0;
- s->cd_sector_size = 0;
- s->atapi_dma = 0;
- s->tray_locked = 0;
- s->tray_open = 0;
- /* ATA DMA state */
- s->io_buffer_size = 0;
- s->req_nb_sectors = 0;
-
- ide_set_signature(s);
- /* init the transfer handler so that 0xffff is returned on data
- accesses */
- s->end_transfer_func = ide_dummy_transfer_stop;
- ide_dummy_transfer_stop(s);
- s->media_changed = 0;
-}
-
void ide_bus_reset(IDEBus *bus)
{
bus->unit = 0;
--
2.4.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 3/5] ide: move buffered DMA cancel to core
2016-01-19 4:51 [Qemu-devel] [PATCH 0/5] ide: fix atapi software reset John Snow
2016-01-19 4:51 ` [Qemu-devel] [PATCH 1/5] ide: Prohibit RESET on IDE drives John Snow
2016-01-19 4:51 ` [Qemu-devel] [PATCH 2/5] ide: code motion John Snow
@ 2016-01-19 4:51 ` John Snow
2016-01-19 11:50 ` Paolo Bonzini
2016-01-19 4:51 ` [Qemu-devel] [PATCH 4/5] ide: Add silent DRQ cancellation John Snow
2016-01-19 4:51 ` [Qemu-devel] [PATCH 5/5] ide: fix device_reset to not ignore pending AIO John Snow
4 siblings, 1 reply; 10+ messages in thread
From: John Snow @ 2016-01-19 4:51 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, John Snow, qemu-devel, stefanha
Buffered DMA cancellation was added to ATAPI devices and implemented
for the BMDMA HBA. Move the code over to common IDE code and allow
it to be used for any HBA.
Signed-off-by: John Snow <jsnow@redhat.com>
---
hw/ide/core.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
hw/ide/internal.h | 1 +
hw/ide/pci.c | 36 +-----------------------------------
3 files changed, 47 insertions(+), 35 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 75486c2..5d81840 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -608,6 +608,51 @@ BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
return aioreq;
}
+/**
+ * Cancel all pending DMA requests.
+ * Any buffered DMA requests are instantly canceled,
+ * but any pending unbuffered DMA requests must be waited on.
+ */
+void ide_cancel_dma_sync(IDEState *s)
+{
+ IDEBufferedRequest *req;
+
+ /* First invoke the callbacks of all buffered requests
+ * and flag those requests as orphaned. Ideally there
+ * are no unbuffered (Scatter Gather DMA Requests or
+ * write requests) pending and we can avoid to drain. */
+ QLIST_FOREACH(req, &s->buffered_requests, list) {
+ if (!req->orphaned) {
+#ifdef DEBUG_IDE
+ printf("%s: invoking cb %p of buffered request %p with"
+ " -ECANCELED\n", __func__, req->original_cb, req);
+#endif
+ req->original_cb(req->original_opaque, -ECANCELED);
+ }
+ req->orphaned = true;
+ }
+
+ /*
+ * We can't cancel Scatter Gather DMA in the middle of the
+ * operation or a partial (not full) DMA transfer would reach
+ * the storage so we wait for completion instead (we beahve
+ * like if the DMA was completed by the time the guest trying
+ * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+ * set).
+ *
+ * In the future we'll be able to safely cancel the I/O if the
+ * whole DMA operation will be submitted to disk with a single
+ * aio operation with preadv/pwritev.
+ */
+ if (s->bus->dma->aiocb) {
+#ifdef DEBUG_IDE
+ printf("%s: draining all remaining requests", __func__);
+#endif
+ blk_drain_all();
+ assert(s->bus->dma->aiocb == NULL);
+ }
+}
+
static void ide_sector_read(IDEState *s);
static void ide_sector_read_cb(void *opaque, int ret)
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 2d1e2d2..86bde26 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -586,6 +586,7 @@ BlockAIOCB *ide_issue_trim(BlockBackend *blk,
BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
QEMUIOVector *iov, int nb_sectors,
BlockCompletionFunc *cb, void *opaque);
+void ide_cancel_dma_sync(IDEState *s);
/* hw/ide/atapi.c */
void ide_atapi_cmd(IDEState *s);
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 37dbc29..6b780b8 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -233,41 +233,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
/* Ignore writes to SSBM if it keeps the old value */
if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
if (!(val & BM_CMD_START)) {
- /* First invoke the callbacks of all buffered requests
- * and flag those requests as orphaned. Ideally there
- * are no unbuffered (Scatter Gather DMA Requests or
- * write requests) pending and we can avoid to drain. */
- IDEBufferedRequest *req;
- IDEState *s = idebus_active_if(bm->bus);
- QLIST_FOREACH(req, &s->buffered_requests, list) {
- if (!req->orphaned) {
-#ifdef DEBUG_IDE
- printf("%s: invoking cb %p of buffered request %p with"
- " -ECANCELED\n", __func__, req->original_cb, req);
-#endif
- req->original_cb(req->original_opaque, -ECANCELED);
- }
- req->orphaned = true;
- }
- /*
- * We can't cancel Scatter Gather DMA in the middle of the
- * operation or a partial (not full) DMA transfer would reach
- * the storage so we wait for completion instead (we beahve
- * like if the DMA was completed by the time the guest trying
- * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
- * set).
- *
- * In the future we'll be able to safely cancel the I/O if the
- * whole DMA operation will be submitted to disk with a single
- * aio operation with preadv/pwritev.
- */
- if (bm->bus->dma->aiocb) {
-#ifdef DEBUG_IDE
- printf("%s: draining all remaining requests", __func__);
-#endif
- blk_drain_all();
- assert(bm->bus->dma->aiocb == NULL);
- }
+ ide_cancel_dma_sync(idebus_active_if(bm->bus));
bm->status &= ~BM_STATUS_DMAING;
} else {
bm->cur_addr = bm->addr;
--
2.4.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] ide: move buffered DMA cancel to core
2016-01-19 4:51 ` [Qemu-devel] [PATCH 3/5] ide: move buffered DMA cancel to core John Snow
@ 2016-01-19 11:50 ` Paolo Bonzini
0 siblings, 0 replies; 10+ messages in thread
From: Paolo Bonzini @ 2016-01-19 11:50 UTC (permalink / raw)
To: John Snow, qemu-block; +Cc: kwolf, qemu-devel, stefanha
On 19/01/2016 05:51, John Snow wrote:
> Buffered DMA cancellation was added to ATAPI devices and implemented
> for the BMDMA HBA. Move the code over to common IDE code and allow
> it to be used for any HBA.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
> hw/ide/core.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> hw/ide/internal.h | 1 +
> hw/ide/pci.c | 36 +-----------------------------------
> 3 files changed, 47 insertions(+), 35 deletions(-)
>
> diff --git a/hw/ide/core.c b/hw/ide/core.c
> index 75486c2..5d81840 100644
> --- a/hw/ide/core.c
> +++ b/hw/ide/core.c
> @@ -608,6 +608,51 @@ BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
> return aioreq;
> }
>
> +/**
> + * Cancel all pending DMA requests.
> + * Any buffered DMA requests are instantly canceled,
> + * but any pending unbuffered DMA requests must be waited on.
> + */
> +void ide_cancel_dma_sync(IDEState *s)
> +{
> + IDEBufferedRequest *req;
> +
> + /* First invoke the callbacks of all buffered requests
> + * and flag those requests as orphaned. Ideally there
> + * are no unbuffered (Scatter Gather DMA Requests or
> + * write requests) pending and we can avoid to drain. */
> + QLIST_FOREACH(req, &s->buffered_requests, list) {
> + if (!req->orphaned) {
> +#ifdef DEBUG_IDE
> + printf("%s: invoking cb %p of buffered request %p with"
> + " -ECANCELED\n", __func__, req->original_cb, req);
> +#endif
> + req->original_cb(req->original_opaque, -ECANCELED);
> + }
> + req->orphaned = true;
> + }
> +
> + /*
> + * We can't cancel Scatter Gather DMA in the middle of the
> + * operation or a partial (not full) DMA transfer would reach
> + * the storage so we wait for completion instead (we beahve
> + * like if the DMA was completed by the time the guest trying
> + * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
> + * set).
> + *
> + * In the future we'll be able to safely cancel the I/O if the
> + * whole DMA operation will be submitted to disk with a single
> + * aio operation with preadv/pwritev.
> + */
> + if (s->bus->dma->aiocb) {
> +#ifdef DEBUG_IDE
> + printf("%s: draining all remaining requests", __func__);
> +#endif
> + blk_drain_all();
As a separate patch you can change this to blk_drain(s->blk), which is
already an improvement.
Paolo
> + assert(s->bus->dma->aiocb == NULL);
> + }
> +}
> +
> static void ide_sector_read(IDEState *s);
>
> static void ide_sector_read_cb(void *opaque, int ret)
> diff --git a/hw/ide/internal.h b/hw/ide/internal.h
> index 2d1e2d2..86bde26 100644
> --- a/hw/ide/internal.h
> +++ b/hw/ide/internal.h
> @@ -586,6 +586,7 @@ BlockAIOCB *ide_issue_trim(BlockBackend *blk,
> BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
> QEMUIOVector *iov, int nb_sectors,
> BlockCompletionFunc *cb, void *opaque);
> +void ide_cancel_dma_sync(IDEState *s);
>
> /* hw/ide/atapi.c */
> void ide_atapi_cmd(IDEState *s);
> diff --git a/hw/ide/pci.c b/hw/ide/pci.c
> index 37dbc29..6b780b8 100644
> --- a/hw/ide/pci.c
> +++ b/hw/ide/pci.c
> @@ -233,41 +233,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
> /* Ignore writes to SSBM if it keeps the old value */
> if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
> if (!(val & BM_CMD_START)) {
> - /* First invoke the callbacks of all buffered requests
> - * and flag those requests as orphaned. Ideally there
> - * are no unbuffered (Scatter Gather DMA Requests or
> - * write requests) pending and we can avoid to drain. */
> - IDEBufferedRequest *req;
> - IDEState *s = idebus_active_if(bm->bus);
> - QLIST_FOREACH(req, &s->buffered_requests, list) {
> - if (!req->orphaned) {
> -#ifdef DEBUG_IDE
> - printf("%s: invoking cb %p of buffered request %p with"
> - " -ECANCELED\n", __func__, req->original_cb, req);
> -#endif
> - req->original_cb(req->original_opaque, -ECANCELED);
> - }
> - req->orphaned = true;
> - }
> - /*
> - * We can't cancel Scatter Gather DMA in the middle of the
> - * operation or a partial (not full) DMA transfer would reach
> - * the storage so we wait for completion instead (we beahve
> - * like if the DMA was completed by the time the guest trying
> - * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
> - * set).
> - *
> - * In the future we'll be able to safely cancel the I/O if the
> - * whole DMA operation will be submitted to disk with a single
> - * aio operation with preadv/pwritev.
> - */
> - if (bm->bus->dma->aiocb) {
> -#ifdef DEBUG_IDE
> - printf("%s: draining all remaining requests", __func__);
> -#endif
> - blk_drain_all();
> - assert(bm->bus->dma->aiocb == NULL);
> - }
> + ide_cancel_dma_sync(idebus_active_if(bm->bus));
> bm->status &= ~BM_STATUS_DMAING;
> } else {
> bm->cur_addr = bm->addr;
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 4/5] ide: Add silent DRQ cancellation
2016-01-19 4:51 [Qemu-devel] [PATCH 0/5] ide: fix atapi software reset John Snow
` (2 preceding siblings ...)
2016-01-19 4:51 ` [Qemu-devel] [PATCH 3/5] ide: move buffered DMA cancel to core John Snow
@ 2016-01-19 4:51 ` John Snow
2016-01-19 4:51 ` [Qemu-devel] [PATCH 5/5] ide: fix device_reset to not ignore pending AIO John Snow
4 siblings, 0 replies; 10+ messages in thread
From: John Snow @ 2016-01-19 4:51 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, John Snow, qemu-devel, stefanha
Split apart the ide_transfer_stop function into two versions: one that
interrupts and one that doesn't. The one that doesn't can be used to
halt any PIO transfers that are in the DRQ phase. It will not halt
any PIO transfers that are currently in the process of buffering data
for the guest to read.
Signed-off-by: John Snow <jsnow@redhat.com>
---
hw/ide/core.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 5d81840..4b4bfe5 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -486,13 +486,26 @@ static void ide_cmd_done(IDEState *s)
}
}
-void ide_transfer_stop(IDEState *s)
+static void ide_transfer_halt(IDEState *s, void(*etf)(IDEState *), bool notify)
{
- s->end_transfer_func = ide_transfer_stop;
+ s->end_transfer_func = etf;
s->data_ptr = s->io_buffer;
s->data_end = s->io_buffer;
s->status &= ~DRQ_STAT;
- ide_cmd_done(s);
+ if (notify) {
+ ide_cmd_done(s);
+ }
+}
+
+void ide_transfer_stop(IDEState *s)
+{
+ ide_transfer_halt(s, ide_transfer_stop, true);
+}
+
+__attribute__((__unused__))
+static void ide_transfer_cancel(IDEState *s)
+{
+ ide_transfer_halt(s, ide_transfer_cancel, false);
}
int64_t ide_get_sector(IDEState *s)
--
2.4.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 5/5] ide: fix device_reset to not ignore pending AIO
2016-01-19 4:51 [Qemu-devel] [PATCH 0/5] ide: fix atapi software reset John Snow
` (3 preceding siblings ...)
2016-01-19 4:51 ` [Qemu-devel] [PATCH 4/5] ide: Add silent DRQ cancellation John Snow
@ 2016-01-19 4:51 ` John Snow
4 siblings, 0 replies; 10+ messages in thread
From: John Snow @ 2016-01-19 4:51 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, John Snow, qemu-devel, stefanha
Signed-off-by: John Snow <jsnow@redhat.com>
---
hw/ide/core.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 4b4bfe5..f728d43 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -502,7 +502,6 @@ void ide_transfer_stop(IDEState *s)
ide_transfer_halt(s, ide_transfer_stop, true);
}
-__attribute__((__unused__))
static void ide_transfer_cancel(IDEState *s)
{
ide_transfer_halt(s, ide_transfer_cancel, false);
@@ -1295,6 +1294,23 @@ static bool cmd_nop(IDEState *s, uint8_t cmd)
return true;
}
+static bool cmd_device_reset(IDEState *s, uint8_t cmd)
+{
+ /* Halt PIO (in the DRQ phase), then DMA */
+ ide_transfer_cancel(s);
+ ide_cancel_dma_sync(s);
+
+ /* Reset any PIO commands, reset signature, etc */
+ ide_reset(s);
+
+ /* RESET: ATA8-ACS3 7.10.4 "Normal Outputs";
+ * ATA8-ACS3 Table 184 "Device Signatures for Normal Output" */
+ s->status = 0x00;
+
+ /* Do not overwrite status register */
+ return false;
+}
+
static bool cmd_data_set_management(IDEState *s, uint8_t cmd)
{
switch (s->feature) {
@@ -1611,15 +1627,6 @@ static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd)
return false;
}
-static bool cmd_device_reset(IDEState *s, uint8_t cmd)
-{
- ide_set_signature(s);
- s->status = 0x00; /* NOTE: READY is _not_ set */
- s->error = 0x01;
-
- return false;
-}
-
static bool cmd_packet(IDEState *s, uint8_t cmd)
{
/* overlapping commands not supported */
--
2.4.3
^ permalink raw reply related [flat|nested] 10+ messages in thread