aboutsummaryrefslogtreecommitdiff
path: root/hw
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
parent1abeb5a65d515f8a8a9cfc4a82342f731bd9321f (diff)
parent09fa35e5cdc7d17ed3e1528ca743893ae77a0ea2 (diff)
Merge remote branch 'origin/master' into pci
Conflicts: Makefile.objs hw/virtio.c
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi_piix4.c55
-rw-r--r--hw/apic.c4
-rw-r--r--hw/e1000.c13
-rw-r--r--hw/hda-audio.c24
-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
-rw-r--r--hw/intel-hda.c69
-rw-r--r--hw/intel-hda.h1
-rw-r--r--hw/mips_malta.c2
-rw-r--r--hw/multiboot.c6
-rw-r--r--hw/pc.c24
-rw-r--r--hw/pc.h3
-rw-r--r--hw/pc_piix.c34
-rw-r--r--hw/pcnet-pci.c345
-rw-r--r--hw/pcnet.c316
-rw-r--r--hw/pcnet.h3
-rw-r--r--hw/ppc_newworld.c2
-rw-r--r--hw/ppc_oldworld.c2
-rw-r--r--hw/ppc_prep.c2
-rw-r--r--hw/scsi-bus.c12
-rw-r--r--hw/scsi-defs.h20
-rw-r--r--hw/scsi-disk.c274
-rw-r--r--hw/scsi-generic.c10
-rw-r--r--hw/scsi.h11
-rw-r--r--hw/sun4u.c2
-rw-r--r--hw/usb-net.c2
-rw-r--r--hw/vga-pci.c44
-rw-r--r--hw/vga.c2
-rw-r--r--hw/vga_int.h2
-rw-r--r--hw/virtio-blk.c6
-rw-r--r--hw/virtio-net.c41
-rw-r--r--hw/virtio-pci.c9
-rw-r--r--hw/vmware_vga.c12
-rw-r--r--hw/xen_disk.c12
39 files changed, 851 insertions, 720 deletions
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index f549089a55..173d78148d 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -52,6 +52,7 @@ struct pci_status {
typedef struct PIIX4PMState {
PCIDevice dev;
+ IORange ioport;
uint16_t pmsts;
uint16_t pmen;
uint16_t pmcntrl;
@@ -128,10 +129,16 @@ static void pm_tmr_timer(void *opaque)
pm_update_sci(s);
}
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width,
+ uint64_t val)
{
- PIIX4PMState *s = opaque;
- addr &= 0x3f;
+ PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
+
+ if (width != 2) {
+ PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n",
+ (unsigned)addr, width, (unsigned)val);
+ }
+
switch(addr) {
case 0x00:
{
@@ -184,12 +191,12 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", addr, val);
}
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
+static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
+ uint64_t *data)
{
- PIIX4PMState *s = opaque;
+ PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport);
uint32_t val;
- addr &= 0x3f;
switch(addr) {
case 0x00:
val = get_pmsts(s);
@@ -200,27 +207,6 @@ static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
case 0x04:
val = s->pmcntrl;
break;
- default:
- val = 0;
- break;
- }
- PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
- return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- // PIIX4PMState *s = opaque;
- PIIX4_DPRINTF("PM writel port=0x%04x val=0x%08x\n", addr & 0x3f, val);
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x3f;
- switch(addr) {
case 0x08:
val = get_pmtmr(s);
break;
@@ -228,10 +214,15 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
val = 0;
break;
}
- PIIX4_DPRINTF("PM readl port=0x%04x val=0x%08x\n", addr, val);
- return val;
+ PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", addr, val);
+ *data = val;
}
+static const IORangeOps pm_iorange_ops = {
+ .read = pm_ioport_read,
+ .write = pm_ioport_write,
+};
+
static void apm_ctrl_changed(uint32_t val, void *arg)
{
PIIX4PMState *s = arg;
@@ -265,10 +256,8 @@ static void pm_io_space_update(PIIX4PMState *s)
/* XXX: need to improve memory and ioport allocation */
PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base);
- register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
- register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
- register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
- register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
+ iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64);
+ ioport_register(&s->ioport);
}
}
diff --git a/hw/apic.c b/hw/apic.c
index 63d62c7553..5f4a87c807 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -437,6 +437,8 @@ static int apic_find_dest(uint8_t dest)
apic = local_apics[i];
if (apic && apic->id == dest)
return i;
+ if (!apic)
+ break;
}
return -1;
@@ -472,6 +474,8 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
set_bit(deliver_bitmask, i);
}
}
+ } else {
+ break;
}
}
}
diff --git a/hw/e1000.c b/hw/e1000.c
index b7f585bc08..57d08cfa35 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -447,9 +447,10 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
// data descriptor
tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
- } else
+ } else {
// legacy descriptor
tp->cptse = 0;
+ }
if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
(tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
@@ -685,8 +686,9 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
(void *)(buf + vlan_offset), size);
desc.length = cpu_to_le16(size + fcs_len(s));
desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
- } else // as per intel docs; skip descriptors with null buf addr
+ } else { // as per intel docs; skip descriptors with null buf addr
DBGOUT(RX, "Null RX descriptor!!\n");
+ }
cpu_physical_memory_write(base, (void *)&desc, sizeof(desc));
if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
@@ -858,13 +860,14 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
- if (index < NWRITEOPS && macreg_writeops[index])
+ if (index < NWRITEOPS && macreg_writeops[index]) {
macreg_writeops[index](s, index, val);
- else if (index < NREADOPS && macreg_readops[index])
+ } else if (index < NREADOPS && macreg_readops[index]) {
DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
- else
+ } else {
DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n",
index<<2, val);
+ }
}
static void
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index 103577470a..c699d6fd8b 100644
--- a/hw/hda-audio.c
+++ b/hw/hda-audio.c
@@ -808,6 +808,28 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
return 0;
}
+static int hda_audio_exit(HDACodecDevice *hda)
+{
+ HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioStream *st;
+ int i;
+
+ dprint(a, 1, "%s\n", __FUNCTION__);
+ for (i = 0; i < ARRAY_SIZE(a->st); i++) {
+ st = a->st + i;
+ if (st->node == NULL) {
+ continue;
+ }
+ if (st->output) {
+ AUD_close_out(&a->card, st->voice.out);
+ } else {
+ AUD_close_in(&a->card, st->voice.in);
+ }
+ }
+ AUD_remove_card(&a->card);
+ return 0;
+}
+
static int hda_audio_post_load(void *opaque, int version)
{
HDAAudioState *a = opaque;
@@ -879,6 +901,7 @@ static HDACodecDeviceInfo hda_audio_info_output = {
.qdev.vmsd = &vmstate_hda_audio,
.qdev.props = hda_audio_properties,
.init = hda_audio_init_output,
+ .exit = hda_audio_exit,
.command = hda_audio_command,
.stream = hda_audio_stream,
};
@@ -890,6 +913,7 @@ static HDACodecDeviceInfo hda_audio_info_duplex = {
.qdev.vmsd = &vmstate_hda_audio,
.qdev.props = hda_audio_properties,
.init = hda_audio_init_duplex,
+ .exit = hda_audio_exit,
.command = hda_audio_command,
.stream = hda_audio_stream,
};
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index ff80dd557f..dfe6091e75 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 bc3e91658a..430350f873 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 d652e06c45..85f4a1607b 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 ec90f266e9..ad406ee24d 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 d46a95eb90..b81b26c532 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 07483e845c..e02b89a38c 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 2001a36b02..66be0c4cce 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;
}
}
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index ccb059dc92..fe316245ad 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -19,6 +19,7 @@
#include "hw.h"
#include "pci.h"
+#include "msi.h"
#include "qemu-timer.h"
#include "audiodev.h"
#include "intel-hda.h"
@@ -55,15 +56,27 @@ static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base)
if (dev->cad == -1) {
dev->cad = bus->next_cad;
}
- if (dev->cad > 15)
+ if (dev->cad >= 15) {
return -1;
+ }
bus->next_cad = dev->cad + 1;
return info->init(dev);
}
+static int hda_codec_dev_exit(DeviceState *qdev)
+{
+ HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
+
+ if (dev->info->exit) {
+ dev->info->exit(dev);
+ }
+ return 0;
+}
+
void hda_codec_register(HDACodecDeviceInfo *info)
{
info->qdev.init = hda_codec_dev_init;
+ info->qdev.exit = hda_codec_dev_exit;
info->qdev.bus_info = &hda_codec_bus_info;
qdev_register(&info->qdev);
}
@@ -177,6 +190,7 @@ struct IntelHDAState {
/* properties */
uint32_t debug;
+ uint32_t msi;
};
struct IntelHDAReg {
@@ -235,7 +249,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
if (d->rirb_sts & ICH6_RBSTS_OVERRUN) {
sts |= (1 << 30);
}
- if (d->state_sts) {
+ if (d->state_sts & d->wake_en) {
sts |= (1 << 30);
}
@@ -257,6 +271,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d)
static void intel_hda_update_irq(IntelHDAState *d)
{
+ int msi = d->msi && msi_enabled(&d->pci);
int level;
intel_hda_update_int_sts(d);
@@ -265,8 +280,15 @@ static void intel_hda_update_irq(IntelHDAState *d)
} else {
level = 0;
}
- dprint(d, 2, "%s: level %d\n", __FUNCTION__, level);
- qemu_set_irq(d->pci.irq[0], level);
+ dprint(d, 2, "%s: level %d [%s]\n", __FUNCTION__,
+ level, msi ? "msi" : "intx");
+ if (msi) {
+ if (level) {
+ msi_notify(&d->pci, 0);
+ }
+ } else {
+ qemu_set_irq(d->pci.irq[0], level);
+ }
}
static int intel_hda_send_command(IntelHDAState *d, uint32_t verb)
@@ -497,6 +519,11 @@ static void intel_hda_set_g_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32
}
}
+static void intel_hda_set_wake_en(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
+{
+ intel_hda_update_irq(d);
+}
+
static void intel_hda_set_state_sts(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old)
{
intel_hda_update_irq(d);
@@ -617,13 +644,15 @@ static const struct IntelHDAReg regtab[] = {
[ ICH6_REG_WAKEEN ] = {
.name = "WAKEEN",
.size = 2,
+ .wmask = 0x7fff,
.offset = offsetof(IntelHDAState, wake_en),
+ .whandler = intel_hda_set_wake_en,
},
[ ICH6_REG_STATESTS ] = {
.name = "STATESTS",
.size = 2,
- .wmask = 0x3fff,
- .wclear = 0x3fff,
+ .wmask = 0x7fff,
+ .wclear = 0x7fff,
.offset = offsetof(IntelHDAState, state_sts),
.whandler = intel_hda_set_state_sts,
},
@@ -1130,6 +1159,9 @@ static int intel_hda_init(PCIDevice *pci)
intel_hda_mmio_write, d);
pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY,
intel_hda_map);
+ if (d->msi) {
+ msi_init(&d->pci, 0x50, 1, true, false);
+ }
hda_codec_bus_init(&d->pci.qdev, &d->codecs,
intel_hda_response, intel_hda_xfer);
@@ -1137,6 +1169,28 @@ static int intel_hda_init(PCIDevice *pci)
return 0;
}
+static int intel_hda_exit(PCIDevice *pci)
+{
+ IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
+
+ if (d->msi) {
+ msi_uninit(&d->pci);
+ }
+ cpu_unregister_io_memory(d->mmio_addr);
+ return 0;
+}
+
+static void intel_hda_write_config(PCIDevice *pci, uint32_t addr,
+ uint32_t val, int len)
+{
+ IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci);
+
+ pci_default_write_config(pci, addr, val, len);
+ if (d->msi) {
+ msi_write_config(pci, addr, val, len);
+ }
+}
+
static int intel_hda_post_load(void *opaque, int version)
{
IntelHDAState* d = opaque;
@@ -1219,8 +1273,11 @@ static PCIDeviceInfo intel_hda_info = {
.qdev.vmsd = &vmstate_intel_hda,
.qdev.reset = intel_hda_reset,
.init = intel_hda_init,
+ .exit = intel_hda_exit,
+ .config_write = intel_hda_write_config,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0),
+ DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1),
DEFINE_PROP_END_OF_LIST(),
}
};
diff --git a/hw/intel-hda.h b/hw/intel-hda.h
index ba290ec850..4e44e3894f 100644
--- a/hw/intel-hda.h
+++ b/hw/intel-hda.h
@@ -32,6 +32,7 @@ struct HDACodecDevice {
struct HDACodecDeviceInfo {
DeviceInfo qdev;
int (*init)(HDACodecDevice *dev);
+ int (*exit)(HDACodecDevice *dev);
void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running);
};
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 80260714ec..6be8aa70f9 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -977,7 +977,7 @@ void mips_malta_init (ram_addr_t ram_size,
} else if (vmsvga_enabled) {
pci_vmsvga_init(pci_bus);
} else if (std_vga_enabled) {
- pci_vga_init(pci_bus, 0, 0);
+ pci_vga_init(pci_bus);
}
}
diff --git a/hw/multiboot.c b/hw/multiboot.c
index f9097a2f60..e710bbb948 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -171,6 +171,12 @@ int load_multiboot(void *fw_cfg,
uint64_t elf_low, elf_high;
int kernel_size;
fclose(f);
+
+ if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
+ fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
+ exit(1);
+ }
+
kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
&elf_low, &elf_high, 0, ELF_MACHINE, 0);
if (kernel_size < 0) {
diff --git a/hw/pc.c b/hw/pc.c
index 69b13bf62c..119c1106c2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -75,12 +75,12 @@ struct e820_entry {
uint64_t address;
uint64_t length;
uint32_t type;
-};
+} __attribute((__packed__, __aligned__(4)));
struct e820_table {
uint32_t count;
struct e820_entry entry[E820_NR_ENTRIES];
-};
+} __attribute((__packed__, __aligned__(4)));
static struct e820_table e820_table;
@@ -430,8 +430,8 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
/* Bochs BIOS messages */
case 0x400:
case 0x401:
- fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
- exit(1);
+ /* used to be panic, now unused */
+ break;
case 0x402:
case 0x403:
#ifdef DEBUG_BIOS
@@ -467,19 +467,19 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
{
- int index = e820_table.count;
+ int index = le32_to_cpu(e820_table.count);
struct e820_entry *entry;
if (index >= E820_NR_ENTRIES)
return -EBUSY;
- entry = &e820_table.entry[index];
+ entry = &e820_table.entry[index++];
- entry->address = address;
- entry->length = length;
- entry->type = type;
+ entry->address = cpu_to_le64(address);
+ entry->length = cpu_to_le64(length);
+ entry->type = cpu_to_le32(type);
- e820_table.count++;
- return e820_table.count;
+ e820_table.count = cpu_to_le32(index);
+ return index;
}
static void *bochs_bios_init(void)
@@ -993,7 +993,7 @@ void pc_vga_init(PCIBus *pci_bus)
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
} else if (std_vga_enabled) {
if (pci_bus) {
- pci_vga_init(pci_bus, 0, 0);
+ pci_vga_init(pci_bus);
} else {
isa_vga_init();
}
diff --git a/hw/pc.h b/hw/pc.h
index 63b0249f2f..68527902a5 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -154,8 +154,7 @@ enum vga_retrace_method {
extern enum vga_retrace_method vga_retrace_method;
int isa_vga_init(void);
-int pci_vga_init(PCIBus *bus,
- unsigned long vga_bios_offset, int vga_bios_size);
+int pci_vga_init(PCIBus *bus);
int isa_vga_mm_init(target_phys_addr_t vram_base,
target_phys_addr_t ctrl_base, int it_shift);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 12359a75c9..7d29d43190 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -212,7 +212,7 @@ static void pc_init_isa(ram_addr_t ram_size,
}
static QEMUMachine pc_machine = {
- .name = "pc-0.13",
+ .name = "pc-0.14",
.alias = "pc",
.desc = "Standard PC",
.init = pc_init_pci,
@@ -220,6 +220,29 @@ static QEMUMachine pc_machine = {
.is_default = 1,
};
+static QEMUMachine pc_machine_v0_13 = {
+ .name = "pc-0.13",
+ .desc = "Standard PC",
+ .init = pc_init_pci,
+ .max_cpus = 255,
+ .compat_props = (GlobalProperty[]) {
+ {
+ .driver = "virtio-9p-pci",
+ .property = "vectors",
+ .value = stringify(0),
+ },{
+ .driver = "VGA",
+ .property = "rombar",
+ .value = stringify(0),
+ },{
+ .driver = "vmware-svga",
+ .property = "rombar",
+ .value = stringify(0),
+ },
+ { /* end of list */ }
+ },
+};
+
static QEMUMachine pc_machine_v0_12 = {
.name = "pc-0.12",
.desc = "Standard PC",
@@ -234,6 +257,14 @@ static QEMUMachine pc_machine_v0_12 = {
.driver = "virtio-serial-pci",
.property = "vectors",
.value = stringify(0),
+ },{
+ .driver = "VGA",
+ .property = "rombar",
+ .value = stringify(0),
+ },{
+ .driver = "vmware-svga",
+ .property = "rombar",
+ .value = stringify(0),
},
{ /* end of list */ }
}
@@ -331,6 +362,7 @@ static QEMUMachine isapc_machine = {
static void pc_machine_init(void)
{
qemu_register_machine(&pc_machine);
+ qemu_register_machine(&pc_machine_v0_13);
qemu_register_machine(&pc_machine_v0_12);
qemu_register_machine(&pc_machine_v0_11);
qemu_register_machine(&pc_machine_v0_10);
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
new file mode 100644
index 0000000000..3dfbe46472
--- /dev/null
+++ b/hw/pcnet-pci.c
@@ -0,0 +1,345 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) PCI emulation
+ *
+ * Copyright (c) 2004 Antony T Curtis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
+ */
+
+#include "pci.h"
+#include "net.h"
+#include "loader.h"
+#include "qemu-timer.h"
+
+#include "pcnet.h"
+
+//#define PCNET_DEBUG
+//#define PCNET_DEBUG_IO
+//#define PCNET_DEBUG_BCR
+//#define PCNET_DEBUG_CSR
+//#define PCNET_DEBUG_RMD
+//#define PCNET_DEBUG_TMD
+//#define PCNET_DEBUG_MATCH
+
+
+typedef struct {
+ PCIDevice pci_dev;
+ PCNetState state;
+} PCIPCNetState;
+
+static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ PCNetState *s = opaque;
+#ifdef PCNET_DEBUG
+ printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+ /* Check APROMWE bit to enable write access */
+ if (pcnet_bcr_readw(s,2) & 0x100)
+ s->prom[addr & 15] = val;
+}
+
+static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
+{
+ PCNetState *s = opaque;
+ uint32_t val = s->prom[addr & 15];
+#ifdef PCNET_DEBUG
+ printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+ return val;
+}
+
+static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
+
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
+ addr, size);
+#endif
+
+ register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
+ register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
+
+ register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
+ register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
+ register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
+ register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
+}
+
+static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr,
+ val);
+#endif
+ if (!(addr & 0x10))
+ pcnet_aprom_writeb(d, addr & 0x0f, val);
+}
+
+static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
+{
+ PCNetState *d = opaque;
+ uint32_t val = -1;
+ if (!(addr & 0x10))
+ val = pcnet_aprom_readb(d, addr & 0x0f);
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr,
+ val & 0xff);
+#endif
+ return val;
+}
+
+static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr,
+ val);
+#endif
+ if (addr & 0x10)
+ pcnet_ioport_writew(d, addr & 0x0f, val);
+ else {
+ addr &= 0x0f;
+ pcnet_aprom_writeb(d, addr, val & 0xff);
+ pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+ }
+}
+
+static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
+{
+ PCNetState *d = opaque;
+ uint32_t val = -1;
+ if (addr & 0x10)
+ val = pcnet_ioport_readw(d, addr & 0x0f);
+ else {
+ addr &= 0x0f;
+ val = pcnet_aprom_readb(d, addr+1);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr);
+ }
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr,
+ val & 0xffff);
+#endif
+ return val;
+}
+
+static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr,
+ val);
+#endif
+ if (addr & 0x10)
+ pcnet_ioport_writel(d, addr & 0x0f, val);
+ else {
+ addr &= 0x0f;
+ pcnet_aprom_writeb(d, addr, val & 0xff);
+ pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+ pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
+ pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
+ }
+}
+
+static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
+{
+ PCNetState *d = opaque;
+ uint32_t val;
+ if (addr & 0x10)
+ val = pcnet_ioport_readl(d, addr & 0x0f);
+ else {
+ addr &= 0x0f;
+ val = pcnet_aprom_readb(d, addr+3);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr+2);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr+1);
+ val <<= 8;
+ val |= pcnet_aprom_readb(d, addr);
+ }
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr,
+ val);
+#endif
+ return val;
+}
+
+static const VMStateDescription vmstate_pci_pcnet = {
+ .name = "pcnet",
+ .version_id = 3,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField []) {
+ VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState),
+ VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+/* PCI interface */
+
+static CPUWriteMemoryFunc * const pcnet_mmio_write[] = {
+ &pcnet_mmio_writeb,
+ &pcnet_mmio_writew,
+ &pcnet_mmio_writel
+};
+
+static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
+ &pcnet_mmio_readb,
+ &pcnet_mmio_readw,
+ &pcnet_mmio_readl
+};
+
+static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
+
+#ifdef PCNET_DEBUG_IO
+ printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
+ addr, size);
+#endif
+
+ cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
+}
+
+static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
+ uint8_t *buf, int len, int do_bswap)
+{
+ cpu_physical_memory_write(addr, buf, len);
+}
+
+static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
+ uint8_t *buf, int len, int do_bswap)
+{
+ cpu_physical_memory_read(addr, buf, len);
+}
+
+static void pci_pcnet_cleanup(VLANClientState *nc)
+{
+ PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
+
+ pcnet_common_cleanup(d);
+}
+
+static int pci_pcnet_uninit(PCIDevice *dev)
+{
+ PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
+
+ cpu_unregister_io_memory(d->state.mmio_index);
+ qemu_del_timer(d->state.poll_timer);
+ qemu_free_timer(d->state.poll_timer);
+ qemu_del_vlan_client(&d->state.nic->nc);
+ return 0;
+}
+
+static NetClientInfo net_pci_pcnet_info = {
+ .type = NET_CLIENT_TYPE_NIC,
+ .size = sizeof(NICState),
+ .can_receive = pcnet_can_receive,
+ .receive = pcnet_receive,
+ .cleanup = pci_pcnet_cleanup,
+};
+
+static int pci_pcnet_init(PCIDevice *pci_dev)
+{
+ PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
+ PCNetState *s = &d->state;
+ uint8_t *pci_conf;
+
+#if 0
+ printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
+ sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
+#endif
+
+ pci_conf = pci_dev->config;
+
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ pci_conf[PCI_REVISION_ID] = 0x10;
+ pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
+
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
+
+ pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
+ pci_conf[PCI_MIN_GNT] = 0x06;
+ pci_conf[PCI_MAX_LAT] = 0xff;
+
+ /* Handler for memory-mapped I/O */
+ s->mmio_index =
+ cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
+
+ pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
+ PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
+
+ pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
+ PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
+
+ s->irq = pci_dev->irq[0];
+ s->phys_mem_read = pci_physical_memory_read;
+ s->phys_mem_write = pci_physical_memory_write;
+
+ if (!pci_dev->qdev.hotplugged) {
+ static int loaded = 0;
+ if (!loaded) {
+ rom_add_option("pxe-pcnet.bin");
+ loaded = 1;
+ }
+ }
+
+ return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
+}
+
+static void pci_reset(DeviceState *dev)
+{
+ PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev);
+
+ pcnet_h_reset(&d->state);
+}
+
+static PCIDeviceInfo pcnet_info = {
+ .qdev.name = "pcnet",
+ .qdev.size = sizeof(PCIPCNetState),
+ .qdev.reset = pci_reset,
+ .qdev.vmsd = &vmstate_pci_pcnet,
+ .init = pci_pcnet_init,
+ .exit = pci_pcnet_uninit,
+ .qdev.props = (Property[]) {
+ DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
+static void pci_pcnet_register_devices(void)
+{
+ pci_qdev_register(&pcnet_info);
+}
+
+device_init(pci_pcnet_register_devices)
diff --git a/hw/pcnet.c b/hw/pcnet.c
index b52935adf1..37010b8fcf 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -35,9 +35,8 @@
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
*/
-#include "pci.h"
+#include "qdev.h"
#include "net.h"
-#include "loader.h"
#include "qemu-timer.h"
#include "qemu_socket.h"
@@ -52,11 +51,6 @@
//#define PCNET_DEBUG_MATCH
-typedef struct {
- PCIDevice pci_dev;
- PCNetState state;
-} PCIPCNetState;
-
struct qemu_ether_header {
uint8_t ether_dhost[6];
uint8_t ether_shost[6];
@@ -704,7 +698,6 @@ static void pcnet_poll_timer(void *opaque);
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
-static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
static void pcnet_s_reset(PCNetState *s)
{
@@ -1048,9 +1041,10 @@ ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_)
int crc_err = 0;
int size = size_;
- if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
+ if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
+ (CSR_LOOP(s) && !s->looptest)) {
return -1;
-
+ }
#ifdef PCNET_DEBUG
printf("pcnet_receive size=%d\n", size);
#endif
@@ -1537,7 +1531,7 @@ static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
}
}
-static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
+uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
{
uint32_t val;
rap &= 127;
@@ -1594,27 +1588,6 @@ void pcnet_h_reset(void *opaque)
pcnet_poll_timer(s);
}
-static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- PCNetState *s = opaque;
-#ifdef PCNET_DEBUG
- printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
-#endif
- /* Check APROMWE bit to enable write access */
- if (pcnet_bcr_readw(s,2) & 0x100)
- s->prom[addr & 15] = val;
-}
-
-static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
-{
- PCNetState *s = opaque;
- uint32_t val = s->prom[addr & 15];
-#ifdef PCNET_DEBUG
- printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
-#endif
- return val;
-}
-
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
{
PCNetState *s = opaque;
@@ -1667,7 +1640,7 @@ uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
return val;
}
-static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
PCNetState *s = opaque;
pcnet_poll_timer(s);
@@ -1697,7 +1670,7 @@ static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
pcnet_update_irq(s);
}
-static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
+uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
{
PCNetState *s = opaque;
uint32_t val = -1;
@@ -1726,125 +1699,6 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
return val;
}
-static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
-
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
- addr, size);
-#endif
-
- register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
- register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
-
- register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
- register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
- register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
- register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
-}
-
-static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PCNetState *d = opaque;
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr,
- val);
-#endif
- if (!(addr & 0x10))
- pcnet_aprom_writeb(d, addr & 0x0f, val);
-}
-
-static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
-{
- PCNetState *d = opaque;
- uint32_t val = -1;
- if (!(addr & 0x10))
- val = pcnet_aprom_readb(d, addr & 0x0f);
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr,
- val & 0xff);
-#endif
- return val;
-}
-
-static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PCNetState *d = opaque;
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr,
- val);
-#endif
- if (addr & 0x10)
- pcnet_ioport_writew(d, addr & 0x0f, val);
- else {
- addr &= 0x0f;
- pcnet_aprom_writeb(d, addr, val & 0xff);
- pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
- }
-}
-
-static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
- PCNetState *d = opaque;
- uint32_t val = -1;
- if (addr & 0x10)
- val = pcnet_ioport_readw(d, addr & 0x0f);
- else {
- addr &= 0x0f;
- val = pcnet_aprom_readb(d, addr+1);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr);
- }
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr,
- val & 0xffff);
-#endif
- return val;
-}
-
-static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PCNetState *d = opaque;
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr,
- val);
-#endif
- if (addr & 0x10)
- pcnet_ioport_writel(d, addr & 0x0f, val);
- else {
- addr &= 0x0f;
- pcnet_aprom_writeb(d, addr, val & 0xff);
- pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
- pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
- pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
- }
-}
-
-static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
- PCNetState *d = opaque;
- uint32_t val;
- if (addr & 0x10)
- val = pcnet_ioport_readl(d, addr & 0x0f);
- else {
- addr &= 0x0f;
- val = pcnet_aprom_readb(d, addr+3);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr+2);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr+1);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr);
- }
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr,
- val);
-#endif
- return val;
-}
-
static bool is_version_2(void *opaque, int version_id)
{
return version_id == 2;
@@ -1874,18 +1728,6 @@ const VMStateDescription vmstate_pcnet = {
}
};
-static const VMStateDescription vmstate_pci_pcnet = {
- .name = "pcnet",
- .version_id = 3,
- .minimum_version_id = 2,
- .minimum_version_id_old = 2,
- .fields = (VMStateField []) {
- VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState),
- VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState),
- VMSTATE_END_OF_LIST()
- }
-};
-
void pcnet_common_cleanup(PCNetState *d)
{
d->nic = NULL;
@@ -1900,147 +1742,3 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
return 0;
}
-
-/* PCI interface */
-
-static CPUWriteMemoryFunc * const pcnet_mmio_write[] = {
- &pcnet_mmio_writeb,
- &pcnet_mmio_writew,
- &pcnet_mmio_writel
-};
-
-static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
- &pcnet_mmio_readb,
- &pcnet_mmio_readw,
- &pcnet_mmio_readl
-};
-
-static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
- pcibus_t addr, pcibus_t size, int type)
-{
- PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
-
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
- addr, size);
-#endif
-
- cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
-}
-
-static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
- uint8_t *buf, int len, int do_bswap)
-{
- cpu_physical_memory_write(addr, buf, len);
-}
-
-static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
- uint8_t *buf, int len, int do_bswap)
-{
- cpu_physical_memory_read(addr, buf, len);
-}
-
-static void pci_pcnet_cleanup(VLANClientState *nc)
-{
- PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
-
- pcnet_common_cleanup(d);
-}
-
-static int pci_pcnet_uninit(PCIDevice *dev)
-{
- PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
-
- cpu_unregister_io_memory(d->state.mmio_index);
- qemu_del_timer(d->state.poll_timer);
- qemu_free_timer(d->state.poll_timer);
- qemu_del_vlan_client(&d->state.nic->nc);
- return 0;
-}
-
-static NetClientInfo net_pci_pcnet_info = {
- .type = NET_CLIENT_TYPE_NIC,
- .size = sizeof(NICState),
- .can_receive = pcnet_can_receive,
- .receive = pcnet_receive,
- .cleanup = pci_pcnet_cleanup,
-};
-
-static int pci_pcnet_init(PCIDevice *pci_dev)
-{
- PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
- PCNetState *s = &d->state;
- uint8_t *pci_conf;
-
-#if 0
- printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
- sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
-#endif
-
- pci_conf = pci_dev->config;
-
- pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
- pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
- pci_set_word(pci_conf + PCI_STATUS,
- PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
- pci_conf[PCI_REVISION_ID] = 0x10;
- pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
-
- pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
- pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
-
- pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
- pci_conf[PCI_MIN_GNT] = 0x06;
- pci_conf[PCI_MAX_LAT] = 0xff;
-
- /* Handler for memory-mapped I/O */
- s->mmio_index =
- cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
-
- pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
- PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
-
- pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
- PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
-
- s->irq = pci_dev->irq[0];
- s->phys_mem_read = pci_physical_memory_read;
- s->phys_mem_write = pci_physical_memory_write;
-
- if (!pci_dev->qdev.hotplugged) {
- static int loaded = 0;
- if (!loaded) {
- rom_add_option("pxe-pcnet.bin");
- loaded = 1;
- }
- }
-
- return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
-}
-
-static void pci_reset(DeviceState *dev)
-{
- PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev);
-
- pcnet_h_reset(&d->state);
-}
-
-static PCIDeviceInfo pcnet_info = {
- .qdev.name = "pcnet",
- .qdev.size = sizeof(PCIPCNetState),
- .qdev.reset = pci_reset,
- .qdev.vmsd = &vmstate_pci_pcnet,
- .init = pci_pcnet_init,
- .exit = pci_pcnet_uninit,
- .qdev.props = (Property[]) {
- DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
- DEFINE_PROP_END_OF_LIST(),
- }
-};
-
-static void pcnet_register_devices(void)
-{
- pci_qdev_register(&pcnet_info);
-}
-
-device_init(pcnet_register_devices)
diff --git a/hw/pcnet.h b/hw/pcnet.h
index efacc9fa59..534bdf9c2b 100644
--- a/hw/pcnet.h
+++ b/hw/pcnet.h
@@ -32,6 +32,9 @@ struct PCNetState_st {
void pcnet_h_reset(void *opaque);
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val);
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr);
+void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val);
+uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr);
+uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
int pcnet_can_receive(VLANClientState *nc);
ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_);
void pcnet_common_cleanup(PCNetState *d);
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 4369337b21..305b2d45e6 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -316,7 +316,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
machine_arch = ARCH_MAC99;
}
/* init basic PC hardware */
- pci_vga_init(pci_bus, 0, 0);
+ pci_vga_init(pci_bus);
escc_mem_index = escc_init(0x80013000, pic[0x25], pic[0x24],
serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index a2f9ddf738..5efc93dc10 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -227,7 +227,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
}
pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
pci_bus = pci_grackle_init(0xfec00000, pic);
- pci_vga_init(pci_bus, 0, 0);
+ pci_vga_init(pci_bus);
escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
serial_hds[1], ESCC_CLOCK, 4);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index a6915f7e68..b1f9cc74f8 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -694,7 +694,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
/* init basic PC hardware */
- pci_vga_init(pci_bus, 0, 0);
+ pci_vga_init(pci_bus);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
// pit = pit_init(0x40, i8259[0]);
rtc_init(2000, NULL);
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 5a3fd4b7ac..93f0e9abc1 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -108,7 +108,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
int res = 0, unit;
loc_push_none(&loc);
- for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
+ for (unit = 0; unit < bus->ndev; unit++) {
dinfo = drive_get(IF_SCSI, bus->busnr, unit);
if (dinfo == NULL) {
continue;
@@ -123,16 +123,6 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
return res;
}
-void scsi_dev_clear_sense(SCSIDevice *dev)
-{
- memset(&dev->sense, 0, sizeof(dev->sense));
-}
-
-void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key)
-{
- dev->sense.key = key;
-}
-
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun)
{
SCSIRequest *req;
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index a4a3518eb8..1473ecbddc 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -111,18 +111,20 @@
#define BLANK 0xa1
/*
- * Status codes
+ * SAM Status codes
*/
#define GOOD 0x00
-#define CHECK_CONDITION 0x01
-#define CONDITION_GOOD 0x02
-#define BUSY 0x04
-#define INTERMEDIATE_GOOD 0x08
-#define INTERMEDIATE_C_GOOD 0x0a
-#define RESERVATION_CONFLICT 0x0c
-#define COMMAND_TERMINATED 0x11
-#define QUEUE_FULL 0x14
+#define CHECK_CONDITION 0x02
+#define CONDITION_GOOD 0x04
+#define BUSY 0x08
+#define INTERMEDIATE_GOOD 0x10
+#define INTERMEDIATE_C_GOOD 0x14
+#define RESERVATION_CONFLICT 0x18
+#define COMMAND_TERMINATED 0x22
+#define TASK_SET_FULL 0x28
+#define ACA_ACTIVE 0x30
+#define TASK_ABORTED 0x40
#define STATUS_MASK 0x3e
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 9628b39a21..6e49404d87 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -41,10 +41,18 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#define SCSI_DMA_BUF_SIZE 131072
#define SCSI_MAX_INQUIRY_LEN 256
-#define SCSI_REQ_STATUS_RETRY 0x01
+#define SCSI_REQ_STATUS_RETRY 0x01
+#define SCSI_REQ_STATUS_RETRY_TYPE_MASK 0x06
+#define SCSI_REQ_STATUS_RETRY_READ 0x00
+#define SCSI_REQ_STATUS_RETRY_WRITE 0x02
+#define SCSI_REQ_STATUS_RETRY_FLUSH 0x04
typedef struct SCSIDiskState SCSIDiskState;
+typedef struct SCSISense {
+ uint8_t key;
+} SCSISense;
+
typedef struct SCSIDiskReq {
SCSIRequest req;
/* ??? We should probably keep track of whether the data transfer is
@@ -68,8 +76,12 @@ struct SCSIDiskState
QEMUBH *bh;
char *version;
char *serial;
+ SCSISense sense;
};
+static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
+static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
+
static SCSIDiskReq *scsi_new_request(SCSIDiskState *s, uint32_t tag,
uint32_t lun)
{
@@ -93,10 +105,22 @@ static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
}
-static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
+static void scsi_disk_clear_sense(SCSIDiskState *s)
+{
+ memset(&s->sense, 0, sizeof(s->sense));
+}
+
+static void scsi_disk_set_sense(SCSIDiskState *s, uint8_t key)
{
- req->status = status;
- scsi_dev_set_sense(req->dev, sense_code);
+ s->sense.key = key;
+}
+
+static void scsi_req_set_status(SCSIDiskReq *r, int status, int sense_code)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+ r->req.status = status;
+ scsi_disk_set_sense(s, sense_code);
}
/* Helper function for command completion. */
@@ -104,7 +128,7 @@ static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
{
DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
r->req.tag, status, sense);
- scsi_req_set_status(&r->req, status, sense);
+ scsi_req_set_status(r, status, sense);
scsi_req_complete(&r->req);
scsi_remove_request(r);
}
@@ -127,34 +151,30 @@ static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
static void scsi_read_complete(void * opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
+ int n;
r->req.aiocb = NULL;
if (ret) {
- DPRINTF("IO error\n");
- r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
- scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
- return;
+ if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_READ)) {
+ return;
+ }
}
+
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
+ n = r->iov.iov_len / 512;
+ r->sector += n;
+ r->sector_count -= n;
r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
}
-/* Read more data from scsi device into buffer. */
-static void scsi_read_data(SCSIDevice *d, uint32_t tag)
+
+static void scsi_read_request(SCSIDiskReq *r)
{
- SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- SCSIDiskReq *r;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t n;
- r = scsi_find_request(s, tag);
- if (!r) {
- BADF("Bad read tag 0x%x\n", tag);
- /* ??? This is the wrong error. */
- scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
- return;
- }
if (r->sector_count == (uint32_t)-1) {
DPRINTF("Read buf_len=%zd\n", r->iov.iov_len);
r->sector_count = 0;
@@ -167,6 +187,9 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
return;
}
+ /* No data transfer may already be in progress */
+ assert(r->req.aiocb == NULL);
+
n = r->sector_count;
if (n > SCSI_DMA_BUF_SIZE / 512)
n = SCSI_DMA_BUF_SIZE / 512;
@@ -175,31 +198,54 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
scsi_read_complete, r);
- if (r->req.aiocb == NULL)
+ if (r->req.aiocb == NULL) {
+ scsi_read_complete(r, -EIO);
+ }
+}
+
+/* Read more data from scsi device into buffer. */
+static void scsi_read_data(SCSIDevice *d, uint32_t tag)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
+ SCSIDiskReq *r;
+
+ r = scsi_find_request(s, tag);
+ if (!r) {
+ BADF("Bad read tag 0x%x\n", tag);
+ /* ??? This is the wrong error. */
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
- r->sector += n;
- r->sector_count -= n;
+ return;
+ }
+
+ scsi_read_request(r);
}
-static int scsi_handle_write_error(SCSIDiskReq *r, int error)
+static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type)
{
+ int is_read = (type == SCSI_REQ_STATUS_RETRY_READ);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- BlockErrorAction action = bdrv_get_on_error(s->bs, 0);
+ BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
if (action == BLOCK_ERR_IGNORE) {
- bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, 0);
+ bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
return 0;
}
if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
|| action == BLOCK_ERR_STOP_ANY) {
- r->status |= SCSI_REQ_STATUS_RETRY;
- bdrv_mon_event(s->bs, BDRV_ACTION_STOP, 0);
+
+ type &= SCSI_REQ_STATUS_RETRY_TYPE_MASK;
+ r->status |= SCSI_REQ_STATUS_RETRY | type;
+
+ bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
vm_stop(0);
} else {
+ if (type == SCSI_REQ_STATUS_RETRY_READ) {
+ r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
+ }
scsi_command_complete(r, CHECK_CONDITION,
HARDWARE_ERROR);
- bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, 0);
+ bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
}
return 1;
@@ -214,8 +260,9 @@ static void scsi_write_complete(void * opaque, int ret)
r->req.aiocb = NULL;
if (ret) {
- if (scsi_handle_write_error(r, -ret))
+ if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_WRITE)) {
return;
+ }
}
n = r->iov.iov_len / 512;
@@ -239,14 +286,17 @@ static void scsi_write_request(SCSIDiskReq *r)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t n;
+ /* No data transfer may already be in progress */
+ assert(r->req.aiocb == NULL);
+
n = r->iov.iov_len / 512;
if (n) {
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
scsi_write_complete, r);
- if (r->req.aiocb == NULL)
- scsi_command_complete(r, CHECK_CONDITION,
- HARDWARE_ERROR);
+ if (r->req.aiocb == NULL) {
+ scsi_write_complete(r, -EIO);
+ }
} else {
/* Invoke completion routine to fetch data from host. */
scsi_write_complete(r, 0);
@@ -268,9 +318,6 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
return 1;
}
- if (r->req.aiocb)
- BADF("Data transfer already in progress\n");
-
scsi_write_request(r);
return 0;
@@ -288,8 +335,25 @@ static void scsi_dma_restart_bh(void *opaque)
QTAILQ_FOREACH(req, &s->qdev.requests, next) {
r = DO_UPCAST(SCSIDiskReq, req, req);
if (r->status & SCSI_REQ_STATUS_RETRY) {
- r->status &= ~SCSI_REQ_STATUS_RETRY;
- scsi_write_request(r);
+ int status = r->status;
+ int ret;
+
+ r->status &=
+ ~(SCSI_REQ_STATUS_RETRY | SCSI_REQ_STATUS_RETRY_TYPE_MASK);
+
+ switch (status & SCSI_REQ_STATUS_RETRY_TYPE_MASK) {
+ case SCSI_REQ_STATUS_RETRY_READ:
+ scsi_read_request(r);
+ break;
+ case SCSI_REQ_STATUS_RETRY_WRITE:
+ scsi_write_request(r);
+ break;
+ case SCSI_REQ_STATUS_RETRY_FLUSH:
+ ret = scsi_disk_emulate_command(r, r->iov.iov_base);
+ if (ret == 0) {
+ scsi_command_complete(r, GOOD, NO_SENSE);
+ }
+ }
}
}
}
@@ -351,15 +415,20 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
switch (page_code) {
case 0x00: /* Supported page codes, mandatory */
+ {
+ int pages;
DPRINTF("Inquiry EVPD[Supported pages] "
"buffer size %zd\n", req->cmd.xfer);
- outbuf[buflen++] = 4; // number of pages
+ pages = buflen++;
outbuf[buflen++] = 0x00; // list of supported pages (this page)
outbuf[buflen++] = 0x80; // unit serial number
outbuf[buflen++] = 0x83; // device identification
- outbuf[buflen++] = 0xb0; // block device characteristics
+ if (bdrv_get_type_hint(s->bs) != BDRV_TYPE_CDROM) {
+ outbuf[buflen++] = 0xb0; // block device characteristics
+ }
+ outbuf[pages] = buflen - pages - 1; // number of pages
break;
-
+ }
case 0x80: /* Device serial number, optional */
{
int l = strlen(s->serial);
@@ -387,7 +456,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
DPRINTF("Inquiry EVPD[Device identification] "
"buffer size %zd\n", req->cmd.xfer);
- outbuf[buflen++] = 3 + id_len;
+ outbuf[buflen++] = 4 + id_len;
outbuf[buflen++] = 0x2; // ASCII
outbuf[buflen++] = 0; // not officially assigned
outbuf[buflen++] = 0; // reserved
@@ -404,6 +473,11 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
unsigned int opt_io_size =
s->qdev.conf.opt_io_size / s->qdev.blocksize;
+ if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+ DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n",
+ page_code);
+ return -1;
+ }
/* required VPD size with unmap support */
outbuf[3] = buflen = 0x3c;
@@ -747,11 +821,13 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
return toclen;
}
-static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
+static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
{
+ SCSIRequest *req = &r->req;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
uint64_t nb_sectors;
int buflen = 0;
+ int ret;
switch (req->cmd.buf[0]) {
case TEST_UNIT_READY:
@@ -763,7 +839,7 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
goto illegal_request;
memset(outbuf, 0, 4);
buflen = 4;
- if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
+ if (s->sense.key == NOT_READY && req->cmd.xfer >= 18) {
memset(outbuf, 0, 18);
buflen = 18;
outbuf[7] = 10;
@@ -773,8 +849,8 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
}
outbuf[0] = 0xf0;
outbuf[1] = 0;
- outbuf[2] = req->dev->sense.key;
- scsi_dev_clear_sense(req->dev);
+ outbuf[2] = s->sense.key;
+ scsi_disk_clear_sense(s);
break;
case INQUIRY:
buflen = scsi_disk_emulate_inquiry(req, outbuf);
@@ -842,7 +918,12 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
buflen = 8;
break;
case SYNCHRONIZE_CACHE:
- bdrv_flush(s->bs);
+ ret = bdrv_flush(s->bs);
+ if (ret < 0) {
+ if (scsi_handle_rw_error(r, -ret, SCSI_REQ_STATUS_RETRY_FLUSH)) {
+ return -1;
+ }
+ }
break;
case GET_CONFIGURATION:
memset(outbuf, 0, 8);
@@ -902,16 +983,16 @@ static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
default:
goto illegal_request;
}
- scsi_req_set_status(req, GOOD, NO_SENSE);
+ scsi_req_set_status(r, GOOD, NO_SENSE);
return buflen;
not_ready:
- scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
- return 0;
+ scsi_command_complete(r, CHECK_CONDITION, NOT_READY);
+ return -1;
illegal_request:
- scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
- return 0;
+ scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
+ return -1;
}
/* Execute a scsi command. Returns the length of the data expected by the
@@ -923,9 +1004,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
uint8_t *buf, int lun)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
- uint64_t lba;
uint32_t len;
- int cmdlen;
int is_write;
uint8_t command;
uint8_t *outbuf;
@@ -944,55 +1023,21 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
outbuf = (uint8_t *)r->iov.iov_base;
is_write = 0;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
- switch (command >> 5) {
- case 0:
- lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
- (((uint64_t) buf[1] & 0x1f) << 16);
- len = buf[4];
- cmdlen = 6;
- break;
- case 1:
- case 2:
- lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
- ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
- len = buf[8] | (buf[7] << 8);
- cmdlen = 10;
- break;
- case 4:
- lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
- ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
- ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
- ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
- len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
- cmdlen = 16;
- break;
- case 5:
- lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
- ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
- len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
- cmdlen = 12;
- break;
- default:
+
+ if (scsi_req_parse(&r->req, buf) != 0) {
BADF("Unsupported command length, command %x\n", command);
goto fail;
}
#ifdef DEBUG_SCSI
{
int i;
- for (i = 1; i < cmdlen; i++) {
+ for (i = 1; i < r->req.cmd.len; i++) {
printf(" 0x%02x", buf[i]);
}
printf("\n");
}
#endif
- if (scsi_req_parse(&r->req, buf) != 0) {
- BADF("Unsupported command length, command %x\n", command);
- goto fail;
- }
- assert(r->req.cmd.len == cmdlen);
- assert(r->req.cmd.lba == lba);
-
if (lun || buf[1] >> 5) {
/* Only LUN 0 supported. */
DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
@@ -1019,23 +1064,22 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case REPORT_LUNS:
case VERIFY:
case REZERO_UNIT:
- rc = scsi_disk_emulate_command(&r->req, outbuf);
- if (rc > 0) {
- r->iov.iov_len = rc;
- } else {
- scsi_req_complete(&r->req);
- scsi_remove_request(r);
+ rc = scsi_disk_emulate_command(r, outbuf);
+ if (rc < 0) {
return 0;
}
+
+ r->iov.iov_len = rc;
break;
case READ_6:
case READ_10:
case READ_12:
case READ_16:
- DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
- if (lba > s->max_lba)
+ len = r->req.cmd.xfer / d->blocksize;
+ DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);
+ if (r->req.cmd.lba > s->max_lba)
goto illegal_lba;
- r->sector = lba * s->cluster_size;
+ r->sector = r->req.cmd.lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
break;
case WRITE_6:
@@ -1045,42 +1089,45 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
case WRITE_VERIFY:
case WRITE_VERIFY_12:
case WRITE_VERIFY_16:
+ len = r->req.cmd.xfer / d->blocksize;
DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",
- (command & 0xe) == 0xe ? "And Verify " : "", lba, len);
- if (lba > s->max_lba)
+ (command & 0xe) == 0xe ? "And Verify " : "",
+ r->req.cmd.lba, len);
+ if (r->req.cmd.lba > s->max_lba)
goto illegal_lba;
- r->sector = lba * s->cluster_size;
+ r->sector = r->req.cmd.lba * s->cluster_size;
r->sector_count = len * s->cluster_size;
is_write = 1;
break;
case MODE_SELECT:
- DPRINTF("Mode Select(6) (len %d)\n", len);
+ DPRINTF("Mode Select(6) (len %lu)\n", (long)r->req.cmd.xfer);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
- if (len > 12) {
+ if (r->req.cmd.xfer > 12) {
goto fail;
}
break;
case MODE_SELECT_10:
- DPRINTF("Mode Select(10) (len %d)\n", len);
+ DPRINTF("Mode Select(10) (len %lu)\n", (long)r->req.cmd.xfer);
/* We don't support mode parameter changes.
Allow the mode parameter header + block descriptors only. */
- if (len > 16) {
+ if (r->req.cmd.xfer > 16) {
goto fail;
}
break;
case SEEK_6:
case SEEK_10:
- DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10, lba);
- if (lba > s->max_lba) {
+ DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
+ r->req.cmd.lba);
+ if (r->req.cmd.lba > s->max_lba) {
goto illegal_lba;
}
break;
default:
- DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
+ DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
fail:
scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
- return 0;
+ return 0;
illegal_lba:
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
return 0;
@@ -1152,11 +1199,6 @@ static int scsi_disk_initfn(SCSIDevice *dev)
return -1;
}
- if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) {
- error_report("Device doesn't support drive option rerror");
- return -1;
- }
-
if (!s->serial) {
/* try to fall back to value set with legacy -drive serial=... */
dinfo = drive_get_by_blockdev(s->bs);
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 7212091695..9be1cca4c3 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -96,17 +96,17 @@ static void scsi_command_complete(void *opaque, int ret)
s->senselen = r->io_header.sb_len_wr;
if (ret != 0)
- r->req.status = BUSY << 1;
+ r->req.status = BUSY;
else {
if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
- r->req.status = BUSY << 1;
+ r->req.status = BUSY;
BADF("Driver Timeout\n");
} else if (r->io_header.status)
r->req.status = r->io_header.status;
else if (s->driver_status & SG_ERR_DRIVER_SENSE)
- r->req.status = CHECK_CONDITION << 1;
+ r->req.status = CHECK_CONDITION;
else
- r->req.status = GOOD << 1;
+ r->req.status = GOOD;
}
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
r, r->req.tag, r->req.status);
@@ -333,7 +333,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
s->senselen = 7;
s->driver_status = SG_ERR_DRIVER_SENSE;
bus = scsi_bus_from_device(d);
- bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION << 1);
+ bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION);
return 0;
}
diff --git a/hw/scsi.h b/hw/scsi.h
index cb06d6d824..bf02adfbe2 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -3,6 +3,7 @@
#include "qdev.h"
#include "block.h"
+#include "blockdev.h"
#include "block_int.h"
#define SCSI_CMD_BUF_SIZE 16
@@ -25,10 +26,6 @@ enum SCSIXferMode {
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
};
-typedef struct SCSISense {
- uint8_t key;
-} SCSISense;
-
typedef struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
@@ -56,7 +53,6 @@ struct SCSIDevice
QTAILQ_HEAD(, SCSIRequest) requests;
int blocksize;
int type;
- struct SCSISense sense;
};
/* cdrom.c */
@@ -86,7 +82,7 @@ struct SCSIBus {
int tcq, ndev;
scsi_completionfn complete;
- SCSIDevice *devs[8];
+ SCSIDevice *devs[MAX_SCSI_DEVS];
};
void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
@@ -101,9 +97,6 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit);
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
-void scsi_dev_clear_sense(SCSIDevice *dev);
-void scsi_dev_set_sense(SCSIDevice *dev, uint8_t key);
-
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag);
void scsi_req_free(SCSIRequest *req);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 45a46d673c..5292ac670f 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -767,7 +767,7 @@ static void sun4uv_init(ram_addr_t RAM_size,
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
&pci_bus3);
isa_mem_base = APB_PCI_IO_BASE;
- pci_vga_init(pci_bus, 0, 0);
+ pci_vga_init(pci_bus);
// XXX Should be pci_bus3
pci_ebus_init(pci_bus, -1);
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 70f9263291..58c672f426 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1142,7 +1142,7 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
break;
default:
- if (usb_net_stringtable[value & 0xff]) {
+ if (ARRAY_SIZE(usb_net_stringtable) > (value & 0xff)) {
ret = set_usb_string(data,
usb_net_stringtable[value & 0xff]);
break;
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 2315f70bca..791ca22763 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -52,14 +52,11 @@ static void vga_map(PCIDevice *pci_dev, int region_num,
{
PCIVGAState *d = (PCIVGAState *)pci_dev;
VGACommonState *s = &d->vga;
- if (region_num == PCI_ROM_SLOT) {
- cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
- } else {
- cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
- s->map_addr = addr;
- s->map_end = addr + s->vram_size;
- vga_dirty_log_start(s);
- }
+
+ cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+ s->map_addr = addr;
+ s->map_end = addr + s->vram_size;
+ vga_dirty_log_start(s);
}
static void pci_vga_write_config(PCIDevice *d,
@@ -95,32 +92,17 @@ static int pci_vga_initfn(PCIDevice *dev)
pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
- if (s->bios_size) {
- unsigned int bios_total_size;
- /* must be a power of two */
- bios_total_size = 1;
- while (bios_total_size < s->bios_size)
- bios_total_size <<= 1;
- pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
- PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
+ if (!dev->rom_bar) {
+ /* compatibility with pc-0.13 and older */
+ vga_init_vbe(s);
}
- vga_init_vbe(s);
- /* ROM BIOS */
- rom_add_vga(VGABIOS_FILENAME);
return 0;
}
-int pci_vga_init(PCIBus *bus,
- unsigned long vga_bios_offset, int vga_bios_size)
+int pci_vga_init(PCIBus *bus)
{
- PCIDevice *dev;
-
- dev = pci_create(bus, -1, "VGA");
- qdev_prop_set_uint32(&dev->qdev, "bios-offset", vga_bios_offset);
- qdev_prop_set_uint32(&dev->qdev, "bios-size", vga_bios_size);
- qdev_init_nofail(&dev->qdev);
-
+ pci_create_simple(bus, -1, "VGA");
return 0;
}
@@ -130,11 +112,7 @@ static PCIDeviceInfo vga_info = {
.qdev.vmsd = &vmstate_vga_pci,
.init = pci_vga_initfn,
.config_write = pci_vga_write_config,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("bios-offset", PCIVGAState, vga.bios_offset, 0),
- DEFINE_PROP_HEX32("bios-size", PCIVGAState, vga.bios_size, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+ .romfile = "vgabios-stdvga.bin",
};
static void vga_register(void)
diff --git a/hw/vga.c b/hw/vga.c
index 966185e03b..c057f4f653 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1934,8 +1934,6 @@ void vga_common_reset(VGACommonState *s)
s->map_addr = 0;
s->map_end = 0;
s->lfb_vram_mapped = 0;
- s->bios_offset = 0;
- s->bios_size = 0;
s->sr_index = 0;
memset(s->sr, '\0', sizeof(s->sr));
s->gr_index = 0;
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 6a46a434fe..bc1327fbf6 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -112,8 +112,6 @@ typedef struct VGACommonState {
uint32_t map_addr;
uint32_t map_end;
uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
- uint32_t bios_offset;
- uint32_t bios_size;
uint32_t latch;
uint8_t sr_index;
uint8_t sr[256];
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index dbe207070e..e5f9b2795a 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -273,7 +273,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
if (!acb) {
- virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_flush_complete(req, -EIO);
}
}
@@ -324,13 +324,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
MultiReqBuffer *mrb)
{
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
- fprintf(stderr, "virtio-blk missing headers\n");
+ error_report("virtio-blk missing headers");
exit(1);
}
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
- fprintf(stderr, "virtio-blk header not in correct element\n");
+ error_report("virtio-blk header not in correct element");
exit(1);
}
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 7e1688cf69..1d61f191b6 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -120,8 +120,8 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
if (!n->vhost_started) {
int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
if (r < 0) {
- fprintf(stderr, "unable to start vhost net: %d: "
- "falling back on userspace virtio\n", -r);
+ error_report("unable to start vhost net: %d: "
+ "falling back on userspace virtio", -r);
} else {
n->vhost_started = 1;
}
@@ -271,7 +271,7 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
uint8_t on;
if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(on)) {
- fprintf(stderr, "virtio-net ctrl invalid rx mode command\n");
+ error_report("virtio-net ctrl invalid rx mode command");
exit(1);
}
@@ -353,7 +353,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
uint16_t vid;
if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(vid)) {
- fprintf(stderr, "virtio-net ctrl invalid vlan command\n");
+ error_report("virtio-net ctrl invalid vlan command");
return VIRTIO_NET_ERR;
}
@@ -381,13 +381,13 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
while (virtqueue_pop(vq, &elem)) {
if ((elem.in_num < 1) || (elem.out_num < 1)) {
- fprintf(stderr, "virtio-net ctrl missing headers\n");
+ error_report("virtio-net ctrl missing headers");
exit(1);
}
if (elem.out_sg[0].iov_len < sizeof(ctrl) ||
elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) {
- fprintf(stderr, "virtio-net ctrl header not in correct element\n");
+ error_report("virtio-net ctrl header not in correct element");
exit(1);
}
@@ -591,21 +591,21 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
if (virtqueue_pop(n->rx_vq, &elem) == 0) {
if (i == 0)
return -1;
- fprintf(stderr, "virtio-net unexpected empty queue: "
+ error_report("virtio-net unexpected empty queue: "
"i %zd mergeable %d offset %zd, size %zd, "
- "guest hdr len %zd, host hdr len %zd guest features 0x%x\n",
+ "guest hdr len %zd, host hdr len %zd guest features 0x%x",
i, n->mergeable_rx_bufs, offset, size,
guest_hdr_len, host_hdr_len, n->vdev.guest_features);
exit(1);
}
if (elem.in_num < 1) {
- fprintf(stderr, "virtio-net receive queue contains no in buffers\n");
+ error_report("virtio-net receive queue contains no in buffers");
exit(1);
}
if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != guest_hdr_len) {
- fprintf(stderr, "virtio-net header not in first element\n");
+ error_report("virtio-net header not in first element");
exit(1);
}
@@ -630,12 +630,11 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
* Otherwise, drop it. */
if (!n->mergeable_rx_bufs && offset < size) {
#if 0
- fprintf(stderr, "virtio-net truncated non-mergeable packet: "
-
- "i %zd mergeable %d offset %zd, size %zd, "
- "guest hdr len %zd, host hdr len %zd\n",
- i, n->mergeable_rx_bufs,
- offset, size, guest_hdr_len, host_hdr_len);
+ error_report("virtio-net truncated non-mergeable packet: "
+ "i %zd mergeable %d offset %zd, size %zd, "
+ "guest hdr len %zd, host hdr len %zd",
+ i, n->mergeable_rx_bufs,
+ offset, size, guest_hdr_len, host_hdr_len);
#endif
return size;
}
@@ -695,7 +694,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
sizeof(struct virtio_net_hdr);
if (out_num < 1 || out_sg->iov_len != hdr_len) {
- fprintf(stderr, "virtio-net header not in first element\n");
+ error_report("virtio-net header not in first element");
exit(1);
}
@@ -981,10 +980,10 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
if (net->tx && strcmp(net->tx, "timer") && strcmp(net->tx, "bh")) {
- fprintf(stderr, "virtio-net: "
- "Unknown option tx=%s, valid options: \"timer\" \"bh\"\n",
- net->tx);
- fprintf(stderr, "Defaulting to \"bh\"\n");
+ error_report("virtio-net: "
+ "Unknown option tx=%s, valid options: \"timer\" \"bh\"",
+ net->tx);
+ error_report("Defaulting to \"bh\"");
}
if (net->tx && !strcmp(net->tx, "timer")) {
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 729917d891..c65765a273 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -254,8 +254,8 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
virtio_queue_set_vector(vdev, vdev->queue_sel, val);
break;
default:
- fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n",
- __func__, addr, val);
+ error_report("%s: unexpected address 0x%x value 0x%x",
+ __func__, addr, val);
break;
}
}
@@ -684,12 +684,14 @@ static int virtio_9p_init_pci(PCIDevice *pci_dev)
VirtIODevice *vdev;
vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
+ vdev->nvectors = proxy->nvectors;
virtio_init_pci(proxy, vdev,
PCI_VENDOR_ID_REDHAT_QUMRANET,
0x1009,
0x2,
0x00);
-
+ /* make the actual value visible */
+ proxy->nvectors = vdev->nvectors;
return 0;
}
#endif
@@ -758,6 +760,7 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_9p_init_pci,
.qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 3d25c14da9..d0f4e1b5b5 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -114,14 +114,12 @@ struct pci_vmsvga_state_s {
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
# define SVGA_IO_MUL 1
# define SVGA_FIFO_SIZE 0x10000
-# define SVGA_MEM_BASE 0xe0000000
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA2
#else
# define SVGA_ID SVGA_ID_1
# define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT
# define SVGA_IO_MUL 4
# define SVGA_FIFO_SIZE 0x10000
-# define SVGA_MEM_BASE 0xe0000000
# define SVGA_PCI_DEVICE_ID PCI_DEVICE_ID_VMWARE_SVGA
#endif
@@ -1219,10 +1217,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
vga_init(&s->vga);
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
- vga_init_vbe(&s->vga);
-
- rom_add_vga(VGABIOS_FILENAME);
-
vmsvga_reset(s);
}
@@ -1307,6 +1301,11 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
vmsvga_init(&s->chip, VGA_RAM_SIZE);
+ if (!dev->rom_bar) {
+ /* compatibility with pc-0.13 and older */
+ vga_init_vbe(&s->chip.vga);
+ }
+
return 0;
}
@@ -1320,6 +1319,7 @@ static PCIDeviceInfo vmsvga_info = {
.qdev.size = sizeof(struct pci_vmsvga_state_s),
.qdev.vmsd = &vmstate_vmware_vga,
.init = pci_vmsvga_initfn,
+ .romfile = "vgabios-vmware.bin",
};
static void vmsvga_register(void)
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 134ac3388e..85a1c85524 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -181,6 +181,10 @@ static int ioreq_parse(struct ioreq *ioreq)
ioreq->prot = PROT_WRITE; /* to memory */
break;
case BLKIF_OP_WRITE_BARRIER:
+ if (!ioreq->req.nr_segments) {
+ ioreq->presync = 1;
+ return 0;
+ }
if (!syncwrite)
ioreq->presync = ioreq->postsync = 1;
/* fall through */
@@ -305,7 +309,7 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
int i, rc, len = 0;
off_t pos;
- if (ioreq_map(ioreq) == -1)
+ if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
goto err;
if (ioreq->presync)
bdrv_flush(blkdev->bs);
@@ -329,6 +333,8 @@ static int ioreq_runio_qemu_sync(struct ioreq *ioreq)
break;
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
+ if (!ioreq->req.nr_segments)
+ break;
pos = ioreq->start;
for (i = 0; i < ioreq->v.niov; i++) {
rc = bdrv_write(blkdev->bs, pos / BLOCK_SIZE,
@@ -386,7 +392,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
{
struct XenBlkDev *blkdev = ioreq->blkdev;
- if (ioreq_map(ioreq) == -1)
+ if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1)
goto err;
ioreq->aio_inflight++;
@@ -403,6 +409,8 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
ioreq->aio_inflight++;
+ if (!ioreq->req.nr_segments)
+ break;
bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE,
&ioreq->v, ioreq->v.size / BLOCK_SIZE,
qemu_aio_complete, ioreq);