diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2010-12-01 07:11:51 +0200 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2010-12-01 07:11:51 +0200 |
commit | c924f36a300cbc54d3cb511116e8e2bae17f5ae6 (patch) | |
tree | 04e57676b1db1db7d8b33934b349f8f37780fa2a /hw | |
parent | 1abeb5a65d515f8a8a9cfc4a82342f731bd9321f (diff) | |
parent | 09fa35e5cdc7d17ed3e1528ca743893ae77a0ea2 (diff) | |
download | qemu-c924f36a300cbc54d3cb511116e8e2bae17f5ae6.zip qemu-c924f36a300cbc54d3cb511116e8e2bae17f5ae6.tar.gz qemu-c924f36a300cbc54d3cb511116e8e2bae17f5ae6.tar.bz2 |
Merge remote branch 'origin/master' into pci
Conflicts:
Makefile.objs
hw/virtio.c
Diffstat (limited to 'hw')
-rw-r--r-- | hw/acpi_piix4.c | 55 | ||||
-rw-r--r-- | hw/apic.c | 4 | ||||
-rw-r--r-- | hw/e1000.c | 13 | ||||
-rw-r--r-- | hw/hda-audio.c | 24 | ||||
-rw-r--r-- | hw/ide/cmd646.c | 8 | ||||
-rw-r--r-- | hw/ide/core.c | 43 | ||||
-rw-r--r-- | hw/ide/internal.h | 2 | ||||
-rw-r--r-- | hw/ide/pci.c | 131 | ||||
-rw-r--r-- | hw/ide/pci.h | 7 | ||||
-rw-r--r-- | hw/ide/piix.c | 8 | ||||
-rw-r--r-- | hw/ide/via.c | 8 | ||||
-rw-r--r-- | hw/intel-hda.c | 69 | ||||
-rw-r--r-- | hw/intel-hda.h | 1 | ||||
-rw-r--r-- | hw/mips_malta.c | 2 | ||||
-rw-r--r-- | hw/multiboot.c | 6 | ||||
-rw-r--r-- | hw/pc.c | 24 | ||||
-rw-r--r-- | hw/pc.h | 3 | ||||
-rw-r--r-- | hw/pc_piix.c | 34 | ||||
-rw-r--r-- | hw/pcnet-pci.c | 345 | ||||
-rw-r--r-- | hw/pcnet.c | 316 | ||||
-rw-r--r-- | hw/pcnet.h | 3 | ||||
-rw-r--r-- | hw/ppc_newworld.c | 2 | ||||
-rw-r--r-- | hw/ppc_oldworld.c | 2 | ||||
-rw-r--r-- | hw/ppc_prep.c | 2 | ||||
-rw-r--r-- | hw/scsi-bus.c | 12 | ||||
-rw-r--r-- | hw/scsi-defs.h | 20 | ||||
-rw-r--r-- | hw/scsi-disk.c | 274 | ||||
-rw-r--r-- | hw/scsi-generic.c | 10 | ||||
-rw-r--r-- | hw/scsi.h | 11 | ||||
-rw-r--r-- | hw/sun4u.c | 2 | ||||
-rw-r--r-- | hw/usb-net.c | 2 | ||||
-rw-r--r-- | hw/vga-pci.c | 44 | ||||
-rw-r--r-- | hw/vga.c | 2 | ||||
-rw-r--r-- | hw/vga_int.h | 2 | ||||
-rw-r--r-- | hw/virtio-blk.c | 6 | ||||
-rw-r--r-- | hw/virtio-net.c | 41 | ||||
-rw-r--r-- | hw/virtio-pci.c | 9 | ||||
-rw-r--r-- | hw/vmware_vga.c | 12 | ||||
-rw-r--r-- | hw/xen_disk.c | 12 |
39 files changed, 851 insertions, 720 deletions
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index f549089..173d781 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); } } @@ -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; } } } @@ -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 1035774..c699d6f 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 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; } } diff --git a/hw/intel-hda.c b/hw/intel-hda.c index ccb059d..fe31624 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 ba290ec..4e44e38 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 8026071..6be8aa7 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 f9097a2..e710bbb 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) { @@ -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(); } @@ -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 12359a7..7d29d43 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 0000000..3dfbe46 --- /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) @@ -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) @@ -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 4369337..305b2d4 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 a2f9ddf..5efc93d 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 a6915f7..b1f9cc7 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 5a3fd4b..93f0e9a 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 a4a3518..1473ecb 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 9628b39..6e49404 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 7212091..9be1cca 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; } @@ -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); @@ -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 70f9263..58c672f 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 2315f70..791ca22 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) @@ -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 6a46a43..bc1327f 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 dbe20707..e5f9b27 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 7e1688c..1d61f19 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 729917d..c65765a 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 3d25c14..d0f4e1b 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 134ac33..85a1c85 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); |