summaryrefslogtreecommitdiffstats
path: root/hw/ide
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-12-01 07:11:51 +0200
committerMichael S. Tsirkin <mst@redhat.com>2010-12-01 07:11:51 +0200
commitc924f36a300cbc54d3cb511116e8e2bae17f5ae6 (patch)
tree04e57676b1db1db7d8b33934b349f8f37780fa2a /hw/ide
parent1abeb5a65d515f8a8a9cfc4a82342f731bd9321f (diff)
parent09fa35e5cdc7d17ed3e1528ca743893ae77a0ea2 (diff)
downloadhqemu-c924f36a300cbc54d3cb511116e8e2bae17f5ae6.zip
hqemu-c924f36a300cbc54d3cb511116e8e2bae17f5ae6.tar.gz
Merge remote branch 'origin/master' into pci
Conflicts: Makefile.objs hw/virtio.c
Diffstat (limited to 'hw/ide')
-rw-r--r--hw/ide/cmd646.c8
-rw-r--r--hw/ide/core.c43
-rw-r--r--hw/ide/internal.h2
-rw-r--r--hw/ide/pci.c131
-rw-r--r--hw/ide/pci.h7
-rw-r--r--hw/ide/piix.c8
-rw-r--r--hw/ide/via.c8
7 files changed, 83 insertions, 124 deletions
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index ff80dd5..dfe6091 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -179,12 +179,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr, 4, 1, bmdma_readb_1, d);
}
- register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
- register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
- register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
- register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
- register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
- register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+ iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
+ ioport_register(&bm->addr_ioport);
addr += 8;
}
}
diff --git a/hw/ide/core.c b/hw/ide/core.c
index bc3e916..430350f 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -473,11 +473,21 @@ static void dma_buf_commit(IDEState *s, int is_write)
qemu_sglist_destroy(&s->sg);
}
+static void ide_dma_set_inactive(BMDMAState *bm)
+{
+ bm->status &= ~BM_STATUS_DMAING;
+ bm->dma_cb = NULL;
+ bm->unit = -1;
+ bm->aiocb = NULL;
+}
+
void ide_dma_error(IDEState *s)
{
ide_transfer_stop(s);
s->error = ABRT_ERR;
s->status = READY_STAT | ERR_STAT;
+ ide_dma_set_inactive(s->bus->bmdma);
+ s->bus->bmdma->status |= BM_STATUS_INT;
ide_set_irq(s->bus);
}
@@ -587,11 +597,8 @@ static void ide_read_dma_cb(void *opaque, int ret)
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus);
eot:
- bm->status &= ~BM_STATUS_DMAING;
bm->status |= BM_STATUS_INT;
- bm->dma_cb = NULL;
- bm->unit = -1;
- bm->aiocb = NULL;
+ ide_dma_set_inactive(bm);
return;
}
@@ -733,11 +740,8 @@ static void ide_write_dma_cb(void *opaque, int ret)
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus);
eot:
- bm->status &= ~BM_STATUS_DMAING;
bm->status |= BM_STATUS_INT;
- bm->dma_cb = NULL;
- bm->unit = -1;
- bm->aiocb = NULL;
+ ide_dma_set_inactive(bm);
return;
}
@@ -811,10 +815,16 @@ static void ide_flush_cb(void *opaque, int ret)
static void ide_flush_cache(IDEState *s)
{
- if (s->bs) {
- bdrv_aio_flush(s->bs, ide_flush_cb, s);
- } else {
+ BlockDriverAIOCB *acb;
+
+ if (s->bs == NULL) {
ide_flush_cb(s, 0);
+ return;
+ }
+
+ acb = bdrv_aio_flush(s->bs, ide_flush_cb, s);
+ if (acb == NULL) {
+ ide_flush_cb(s, -EIO);
}
}
@@ -1055,11 +1065,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
ide_set_irq(s->bus);
eot:
- bm->status &= ~BM_STATUS_DMAING;
bm->status |= BM_STATUS_INT;
- bm->dma_cb = NULL;
- bm->unit = -1;
- bm->aiocb = NULL;
+ ide_dma_set_inactive(bm);
return;
}
@@ -2948,12 +2955,10 @@ void ide_dma_cancel(BMDMAState *bm)
printf("aio_cancel\n");
#endif
bdrv_aio_cancel(bm->aiocb);
- bm->aiocb = NULL;
}
- bm->status &= ~BM_STATUS_DMAING;
+
/* cancel DMA request */
- bm->unit = -1;
- bm->dma_cb = NULL;
+ ide_dma_set_inactive(bm);
}
}
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index d652e06..85f4a16 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -8,6 +8,7 @@
*/
#include <hw/ide.h>
#include "block_int.h"
+#include "iorange.h"
/* debug IDE devices */
//#define DEBUG_IDE
@@ -496,6 +497,7 @@ struct BMDMAState {
QEMUIOVector qiov;
int64_t sector_num;
uint32_t nsector;
+ IORange addr_ioport;
QEMUBH *bh;
};
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index ec90f26..ad406ee 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -39,106 +39,75 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
#ifdef DEBUG_IDE
printf("%s: 0x%08x\n", __func__, val);
#endif
- if (!(val & BM_CMD_START)) {
- /*
- * 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->aiocb) {
- qemu_aio_flush();
+
+ /* 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)) {
+ /*
+ * 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->aiocb) {
+ qemu_aio_flush();
#ifdef DEBUG_IDE
- if (bm->aiocb)
- printf("ide_dma_cancel: aiocb still pending");
- if (bm->status & BM_STATUS_DMAING)
- printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+ if (bm->aiocb)
+ printf("ide_dma_cancel: aiocb still pending");
+ if (bm->status & BM_STATUS_DMAING)
+ printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
#endif
+ }
+ } else {
+ bm->cur_addr = bm->addr;
+ if (!(bm->status & BM_STATUS_DMAING)) {
+ bm->status |= BM_STATUS_DMAING;
+ /* start dma transfer if possible */
+ if (bm->dma_cb)
+ bm->dma_cb(bm, 0);
+ }
}
- bm->cmd = val & 0x09;
- } else {
- if (!(bm->status & BM_STATUS_DMAING)) {
- bm->status |= BM_STATUS_DMAING;
- /* start dma transfer if possible */
- if (bm->dma_cb)
- bm->dma_cb(bm, 0);
- }
- bm->cmd = val & 0x09;
}
-}
-uint32_t bmdma_addr_readb(void *opaque, uint32_t addr)
-{
- BMDMAState *bm = opaque;
- uint32_t val;
- val = (bm->addr >> ((addr & 3) * 8)) & 0xff;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- return val;
+ bm->cmd = val & 0x09;
}
-void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void bmdma_addr_read(IORange *ioport, uint64_t addr,
+ unsigned width, uint64_t *data)
{
- BMDMAState *bm = opaque;
- int shift = (addr & 3) * 8;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- bm->addr &= ~(0xFF << shift);
- bm->addr |= ((val & 0xFF) << shift) & ~3;
- bm->cur_addr = bm->addr;
-}
+ BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
+ uint32_t mask = (1ULL << (width * 8)) - 1;
-uint32_t bmdma_addr_readw(void *opaque, uint32_t addr)
-{
- BMDMAState *bm = opaque;
- uint32_t val;
- val = (bm->addr >> ((addr & 3) * 8)) & 0xffff;
+ *data = (bm->addr >> (addr * 8)) & mask;
#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
+ printf("%s: 0x%08x\n", __func__, (unsigned)*data);
#endif
- return val;
}
-void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val)
+static void bmdma_addr_write(IORange *ioport, uint64_t addr,
+ unsigned width, uint64_t data)
{
- BMDMAState *bm = opaque;
- int shift = (addr & 3) * 8;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- bm->addr &= ~(0xFFFF << shift);
- bm->addr |= ((val & 0xFFFF) << shift) & ~3;
- bm->cur_addr = bm->addr;
-}
+ BMDMAState *bm = container_of(ioport, BMDMAState, addr_ioport);
+ int shift = addr * 8;
+ uint32_t mask = (1ULL << (width * 8)) - 1;
-uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
-{
- BMDMAState *bm = opaque;
- uint32_t val;
- val = bm->addr;
#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
+ printf("%s: 0x%08x\n", __func__, (unsigned)data);
#endif
- return val;
+ bm->addr &= ~(mask << shift);
+ bm->addr |= ((data & mask) << shift) & ~3;
}
-void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- BMDMAState *bm = opaque;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- bm->addr = val & ~3;
- bm->cur_addr = bm->addr;
-}
+const IORangeOps bmdma_addr_ioport_ops = {
+ .read = bmdma_addr_read,
+ .write = bmdma_addr_write,
+};
static bool ide_bmdma_current_needed(void *opaque)
{
diff --git a/hw/ide/pci.h b/hw/ide/pci.h
index d46a95e..b81b26c 100644
--- a/hw/ide/pci.h
+++ b/hw/ide/pci.h
@@ -11,12 +11,7 @@ typedef struct PCIIDEState {
} PCIIDEState;
void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t bmdma_addr_readb(void *opaque, uint32_t addr);
-void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t bmdma_addr_readw(void *opaque, uint32_t addr);
-void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val);
-uint32_t bmdma_addr_readl(void *opaque, uint32_t addr);
-void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val);
+extern const IORangeOps bmdma_addr_ioport_ops;
void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table);
extern const VMStateDescription vmstate_ide_pci;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 07483e8..e02b89a 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -85,12 +85,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
register_ioport_read(addr, 4, 1, bmdma_readb, bm);
- register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
- register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
- register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
- register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
- register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
- register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+ iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
+ ioport_register(&bm->addr_ioport);
addr += 8;
}
}
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 2001a36..66be0c4 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -87,12 +87,8 @@ static void bmdma_map(PCIDevice *pci_dev, int region_num,
register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
register_ioport_read(addr, 4, 1, bmdma_readb, bm);
- register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm);
- register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm);
- register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm);
- register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm);
- register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
- register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+ iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4);
+ ioport_register(&bm->addr_ioport);
addr += 8;
}
}
OpenPOWER on IntegriCloud