diff options
Diffstat (limited to 'hw/ide')
| -rw-r--r-- | hw/ide/ahci.c | 182 | ||||
| -rw-r--r-- | hw/ide/ahci.h | 19 | ||||
| -rw-r--r-- | hw/ide/atapi.c | 69 | ||||
| -rw-r--r-- | hw/ide/core.c | 14 | ||||
| -rw-r--r-- | hw/ide/ich.c | 10 | ||||
| -rw-r--r-- | hw/ide/internal.h | 2 | ||||
| -rw-r--r-- | hw/ide/macio.c | 12 | ||||
| -rw-r--r-- | hw/ide/pci.c | 7 |
8 files changed, 237 insertions, 78 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 21f76ed86e..dd1912e80d 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -378,17 +378,23 @@ static uint64_t ahci_mem_read(void *opaque, hwaddr addr, unsigned size) int ofst = addr - aligned; uint64_t lo = ahci_mem_read_32(opaque, aligned); uint64_t hi; + uint64_t val; /* if < 8 byte read does not cross 4 byte boundary */ if (ofst + size <= 4) { - return lo >> (ofst * 8); + val = lo >> (ofst * 8); + } else { + g_assert_cmpint(size, >, 1); + + /* If the 64bit read is unaligned, we will produce undefined + * results. AHCI does not support unaligned 64bit reads. */ + hi = ahci_mem_read_32(opaque, aligned + 4); + val = (hi << 32 | lo) >> (ofst * 8); } - g_assert_cmpint(size, >, 1); - /* If the 64bit read is unaligned, we will produce undefined - * results. AHCI does not support unaligned 64bit reads. */ - hi = ahci_mem_read_32(opaque, aligned + 4); - return (hi << 32 | lo) >> (ofst * 8); + DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n", + addr, val, size); + return val; } @@ -397,6 +403,9 @@ static void ahci_mem_write(void *opaque, hwaddr addr, { AHCIState *s = opaque; + DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n", + addr, val, size); + /* Only aligned reads are allowed on AHCI */ if (addr & 3) { fprintf(stderr, "ahci: Mis-aligned write to addr 0x" @@ -804,8 +813,21 @@ static int prdt_tbl_entry_size(const AHCI_SG *tbl) return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1; } +/** + * Fetch entries in a guest-provided PRDT and convert it into a QEMU SGlist. + * @ad: The AHCIDevice for whom we are building the SGList. + * @sglist: The SGList target to add PRD entries to. + * @cmd: The AHCI Command Header that describes where the PRDT is. + * @limit: The remaining size of the S/ATA transaction, in bytes. + * @offset: The number of bytes already transferred, in bytes. + * + * The AHCI PRDT can describe up to 256GiB. S/ATA only support transactions of + * up to 32MiB as of ATA8-ACS3 rev 1b, assuming a 512 byte sector size. We stop + * building the sglist from the PRDT as soon as we hit @limit bytes, + * which is <= INT32_MAX/2GiB. + */ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, - AHCICmdHdr *cmd, int64_t limit, int32_t offset) + AHCICmdHdr *cmd, int64_t limit, uint64_t offset) { uint16_t opts = le16_to_cpu(cmd->opts); uint16_t prdtl = le16_to_cpu(cmd->prdtl); @@ -823,14 +845,6 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, IDEBus *bus = &ad->port; BusState *qbus = BUS(bus); - /* - * Note: AHCI PRDT can describe up to 256GiB. SATA/ATA only support - * transactions of up to 32MiB as of ATA8-ACS3 rev 1b, assuming a - * 512 byte sector size. We limit the PRDT in this implementation to - * a reasonably large 2GiB, which can accommodate the maximum transfer - * request for sector sizes up to 32K. - */ - if (!prdtl) { DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts); return -1; @@ -880,13 +894,6 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), MIN(prdt_tbl_entry_size(&tbl[i]), limit - sglist->size)); - if (sglist->size > INT32_MAX) { - error_report("AHCI Physical Region Descriptor Table describes " - "more than 2 GiB."); - qemu_sglist_destroy(sglist); - r = -1; - goto out; - } } } @@ -1427,24 +1434,26 @@ static const IDEDMAOps ahci_dma_ops = { .cmd_done = ahci_cmd_done, }; -void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) +void ahci_init(AHCIState *s, DeviceState *qdev) { - qemu_irq *irqs; - int i; - - s->as = as; - s->ports = ports; - s->dev = g_new0(AHCIDevice, ports); s->container = qdev; - ahci_reg_init(s); /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s, "ahci", AHCI_MEM_BAR_SIZE); memory_region_init_io(&s->idp, OBJECT(qdev), &ahci_idp_ops, s, "ahci-idp", 32); +} - irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); +void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) +{ + qemu_irq *irqs; + int i; + s->as = as; + s->ports = ports; + s->dev = g_new0(AHCIDevice, ports); + ahci_reg_init(s); + irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); for (i = 0; i < s->ports; i++) { AHCIDevice *ad = &s->dev[i]; @@ -1639,17 +1648,24 @@ static void sysbus_ahci_reset(DeviceState *dev) ahci_reset(&s->ahci); } -static void sysbus_ahci_realize(DeviceState *dev, Error **errp) +static void sysbus_ahci_init(Object *obj) { - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - SysbusAHCIState *s = SYSBUS_AHCI(dev); + SysbusAHCIState *s = SYSBUS_AHCI(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - ahci_init(&s->ahci, dev, &address_space_memory, s->num_ports); + ahci_init(&s->ahci, DEVICE(obj)); sysbus_init_mmio(sbd, &s->ahci.mem); sysbus_init_irq(sbd, &s->ahci.irq); } +static void sysbus_ahci_realize(DeviceState *dev, Error **errp) +{ + SysbusAHCIState *s = SYSBUS_AHCI(dev); + + ahci_realize(&s->ahci, dev, &address_space_memory, s->num_ports); +} + static Property sysbus_ahci_properties[] = { DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, num_ports, 1), DEFINE_PROP_END_OF_LIST(), @@ -1670,12 +1686,108 @@ static const TypeInfo sysbus_ahci_info = { .name = TYPE_SYSBUS_AHCI, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SysbusAHCIState), + .instance_init = sysbus_ahci_init, .class_init = sysbus_ahci_class_init, }; +#define ALLWINNER_AHCI_BISTAFR ((0xa0 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_BISTCR ((0xa4 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_BISTFCTR ((0xa8 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_BISTSR ((0xac - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_BISTDECR ((0xb0 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_DIAGNR0 ((0xb4 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_DIAGNR1 ((0xb8 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_OOBR ((0xbc - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_PHYCS0R ((0xc0 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_PHYCS1R ((0xc4 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_PHYCS2R ((0xc8 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_TIMER1MS ((0xe0 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_GPARAM1R ((0xe8 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_GPARAM2R ((0xec - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_PPARAMR ((0xf0 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_TESTR ((0xf4 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_VERSIONR ((0xf8 - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_IDR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) +#define ALLWINNER_AHCI_RWCR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) + +static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr, + unsigned size) +{ + AllwinnerAHCIState *a = opaque; + uint64_t val = a->regs[addr/4]; + + switch (addr / 4) { + case ALLWINNER_AHCI_PHYCS0R: + val |= 0x2 << 28; + break; + case ALLWINNER_AHCI_PHYCS2R: + val &= ~(0x1 << 24); + break; + } + DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n", + addr, val, size); + return val; +} + +static void allwinner_ahci_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + AllwinnerAHCIState *a = opaque; + + DPRINTF(-1, "addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 ", size=%d\n", + addr, val, size); + a->regs[addr/4] = val; +} + +static const MemoryRegionOps allwinner_ahci_mem_ops = { + .read = allwinner_ahci_mem_read, + .write = allwinner_ahci_mem_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void allwinner_ahci_init(Object *obj) +{ + SysbusAHCIState *s = SYSBUS_AHCI(obj); + AllwinnerAHCIState *a = ALLWINNER_AHCI(obj); + + memory_region_init_io(&a->mmio, OBJECT(obj), &allwinner_ahci_mem_ops, a, + "allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE); + memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF, + &a->mmio); +} + +static const VMStateDescription vmstate_allwinner_ahci = { + .name = "allwinner-ahci", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, AllwinnerAHCIState, + ALLWINNER_AHCI_MMIO_SIZE/4), + VMSTATE_END_OF_LIST() + } +}; + +static void allwinner_ahci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_allwinner_ahci; +} + +static const TypeInfo allwinner_ahci_info = { + .name = TYPE_ALLWINNER_AHCI, + .parent = TYPE_SYSBUS_AHCI, + .instance_size = sizeof(AllwinnerAHCIState), + .instance_init = allwinner_ahci_init, + .class_init = allwinner_ahci_class_init, +}; + static void sysbus_ahci_register_types(void) { type_register_static(&sysbus_ahci_info); + type_register_static(&allwinner_ahci_info); } type_init(sysbus_ahci_register_types) diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index c9b3805415..bc777ed5c2 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -366,7 +366,8 @@ typedef struct SDBFIS { uint32_t payload; } QEMU_PACKED SDBFIS; -void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports); +void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports); +void ahci_init(AHCIState *s, DeviceState *qdev); void ahci_uninit(AHCIState *s); void ahci_reset(AHCIState *s); @@ -385,4 +386,20 @@ typedef struct SysbusAHCIState { uint32_t num_ports; } SysbusAHCIState; +#define TYPE_ALLWINNER_AHCI "allwinner-ahci" +#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ + TYPE_ALLWINNER_AHCI) + +#define ALLWINNER_AHCI_MMIO_OFF 0x80 +#define ALLWINNER_AHCI_MMIO_SIZE 0x80 + +struct AllwinnerAHCIState { + /*< private >*/ + SysbusAHCIState parent_obj; + /*< public >*/ + + MemoryRegion mmio; + uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4]; +}; + #endif /* HW_IDE_AHCI_H */ diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 747f46611e..ed8bb2c80a 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -108,27 +108,30 @@ static void cd_data_to_raw(uint8_t *buf, int lba) static int cd_read_sector(IDEState *s, int lba, uint8_t *buf, int sector_size) { int ret; + block_acct_start(blk_get_stats(s->blk), &s->acct, + 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); switch(sector_size) { case 2048: - block_acct_start(blk_get_stats(s->blk), &s->acct, - 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); ret = blk_read(s->blk, (int64_t)lba << 2, buf, 4); - block_acct_done(blk_get_stats(s->blk), &s->acct); break; case 2352: - block_acct_start(blk_get_stats(s->blk), &s->acct, - 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); ret = blk_read(s->blk, (int64_t)lba << 2, buf + 16, 4); - block_acct_done(blk_get_stats(s->blk), &s->acct); - if (ret < 0) - return ret; - cd_data_to_raw(buf, lba); + if (ret >= 0) { + cd_data_to_raw(buf, lba); + } break; default: - ret = -EIO; - break; + block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ); + return -EIO; + } + + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { + block_acct_done(blk_get_stats(s->blk), &s->acct); } + return ret; } @@ -167,6 +170,17 @@ void ide_atapi_io_error(IDEState *s, int ret) } } +static uint16_t atapi_byte_count_limit(IDEState *s) +{ + uint16_t bcl; + + bcl = s->lcyl | (s->hcyl << 8); + if (bcl == 0xffff) { + return 0xfffe; + } + return bcl; +} + /* The whole ATAPI transfer logic is handled in this function */ void ide_atapi_cmd_reply_end(IDEState *s) { @@ -209,12 +223,10 @@ void ide_atapi_cmd_reply_end(IDEState *s) } else { /* a new transfer is needed */ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; - byte_count_limit = s->lcyl | (s->hcyl << 8); + byte_count_limit = atapi_byte_count_limit(s); #ifdef DEBUG_IDE_ATAPI printf("byte_count_limit=%d\n", byte_count_limit); #endif - if (byte_count_limit == 0xffff) - byte_count_limit--; size = s->packet_transfer_size; if (size > byte_count_limit) { /* byte count limit must be even if this case */ @@ -357,7 +369,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) return; eot: - block_acct_done(blk_get_stats(s->blk), &s->acct); + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { + block_acct_done(blk_get_stats(s->blk), &s->acct); + } ide_set_inactive(s, false); } @@ -1179,7 +1195,7 @@ enum { NONDATA = 0x04, }; -static const struct { +static const struct AtapiCmd { void (*handler)(IDEState *s, uint8_t *buf); int flags; } atapi_cmd_table[0x100] = { @@ -1206,9 +1222,9 @@ static const struct { void ide_atapi_cmd(IDEState *s) { - uint8_t *buf; + uint8_t *buf = s->io_buffer; + const struct AtapiCmd *cmd = &atapi_cmd_table[s->io_buffer[0]]; - buf = s->io_buffer; #ifdef DEBUG_IDE_ATAPI { int i; @@ -1219,14 +1235,14 @@ void ide_atapi_cmd(IDEState *s) printf("\n"); } #endif + /* * If there's a UNIT_ATTENTION condition pending, only command flagged with * ALLOW_UA are allowed to complete. with other commands getting a CHECK * condition response unless a higher priority status, defined by the drive * here, is pending. */ - if (s->sense_key == UNIT_ATTENTION && - !(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA)) { + if (s->sense_key == UNIT_ATTENTION && !(cmd->flags & ALLOW_UA)) { ide_atapi_cmd_check_status(s); return; } @@ -1237,7 +1253,7 @@ void ide_atapi_cmd(IDEState *s) * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close * states rely on this behavior. */ - if (!(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA) && + if (!(cmd->flags & ALLOW_UA) && !s->tray_open && blk_is_inserted(s->blk) && s->cdrom_changed) { if (s->cdrom_changed == 1) { @@ -1252,7 +1268,7 @@ void ide_atapi_cmd(IDEState *s) } /* Report a Not Ready condition if appropriate for the command */ - if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) && + if ((cmd->flags & CHECK_READY) && (!media_present(s) || !blk_is_inserted(s->blk))) { ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT); @@ -1263,10 +1279,9 @@ void ide_atapi_cmd(IDEState *s) * If this is a data-transferring PIO command and BCL is 0, * we abort at the /ATA/ level, not the ATAPI level. * See ATA8 ACS3 section 7.17.6.49 and 7.21.5 */ - if (!(atapi_cmd_table[s->io_buffer[0]].flags & NONDATA)) { + if (cmd->handler && !(cmd->flags & NONDATA)) { /* TODO: Check IDENTIFY data word 125 for default BCL (currently 0) */ - uint16_t byte_count_limit = s->lcyl | (s->hcyl << 8); - if (!(byte_count_limit || s->atapi_dma)) { + if (!(atapi_byte_count_limit(s) || s->atapi_dma)) { /* TODO: Move abort back into core.c and make static inline again */ ide_abort_command(s); return; @@ -1274,8 +1289,8 @@ void ide_atapi_cmd(IDEState *s) } /* Execute the command */ - if (atapi_cmd_table[s->io_buffer[0]].handler) { - atapi_cmd_table[s->io_buffer[0]].handler(s, buf); + if (cmd->handler) { + cmd->handler(s, buf); return; } diff --git a/hw/ide/core.c b/hw/ide/core.c index 317406dca3..2725dd3b81 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -574,7 +574,6 @@ static void ide_sector_read_cb(void *opaque, int ret) if (ret == -ECANCELED) { return; } - block_acct_done(blk_get_stats(s->blk), &s->acct); if (ret != 0) { if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO | IDE_RETRY_READ)) { @@ -582,6 +581,8 @@ static void ide_sector_read_cb(void *opaque, int ret) } } + block_acct_done(blk_get_stats(s->blk), &s->acct); + n = s->nsector; if (n > s->req_nb_sectors) { n = s->req_nb_sectors; @@ -621,6 +622,7 @@ static void ide_sector_read(IDEState *s) if (!ide_sect_range_ok(s, sector_num, n)) { ide_rw_error(s); + block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ); return; } @@ -672,6 +674,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) assert(s->bus->retry_unit == s->unit); s->bus->error_status = op; } else if (action == BLOCK_ERROR_ACTION_REPORT) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); if (op & IDE_RETRY_DMA) { ide_dma_error(s); } else { @@ -750,6 +753,7 @@ static void ide_dma_cb(void *opaque, int ret) if ((s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) && !ide_sect_range_ok(s, sector_num, n)) { ide_dma_error(s); + block_acct_invalid(blk_get_stats(s->blk), s->acct.type); return; } @@ -826,7 +830,6 @@ static void ide_sector_write_cb(void *opaque, int ret) if (ret == -ECANCELED) { return; } - block_acct_done(blk_get_stats(s->blk), &s->acct); s->pio_aiocb = NULL; s->status &= ~BUSY_STAT; @@ -837,6 +840,8 @@ static void ide_sector_write_cb(void *opaque, int ret) } } + block_acct_done(blk_get_stats(s->blk), &s->acct); + n = s->nsector; if (n > s->req_nb_sectors) { n = s->req_nb_sectors; @@ -887,6 +892,7 @@ static void ide_sector_write(IDEState *s) if (!ide_sect_range_ok(s, sector_num, n)) { ide_rw_error(s); + block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE); return; } @@ -895,7 +901,7 @@ static void ide_sector_write(IDEState *s) qemu_iovec_init_external(&s->qiov, &s->iov, 1); block_acct_start(blk_get_stats(s->blk), &s->acct, - n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ); + n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE); s->pio_aiocb = blk_aio_writev(s->blk, sector_num, &s->qiov, n, ide_sector_write_cb, s); } @@ -2312,7 +2318,7 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, if (version) { pstrcpy(s->version, sizeof(s->version), version); } else { - pstrcpy(s->version, sizeof(s->version), qemu_get_version()); + pstrcpy(s->version, sizeof(s->version), qemu_hw_version()); } ide_reset(s); diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 350c7f1c75..16925fa258 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -97,6 +97,13 @@ static void pci_ich9_reset(DeviceState *dev) ahci_reset(&d->ahci); } +static void pci_ich9_ahci_init(Object *obj) +{ + struct AHCIPCIState *d = ICH_AHCI(obj); + + ahci_init(&d->ahci, DEVICE(obj)); +} + static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp) { struct AHCIPCIState *d; @@ -104,7 +111,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp) uint8_t *sata_cap; d = ICH_AHCI(dev); - ahci_init(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6); + ahci_realize(&d->ahci, DEVICE(dev), pci_get_address_space(dev), 6); pci_config_set_prog_interface(dev->config, AHCI_PROGMODE_MAJOR_REV_1); @@ -171,6 +178,7 @@ static const TypeInfo ich_ahci_info = { .name = TYPE_ICH9_AHCI, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(AHCIPCIState), + .instance_init = pci_ich9_ahci_init, .class_init = ich_ahci_class_init, }; diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 05e93ffe3b..e4629b023a 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -397,7 +397,7 @@ struct IDEState { struct iovec iov; QEMUIOVector qiov; /* ATA DMA state */ - int32_t io_buffer_offset; + uint64_t io_buffer_offset; int32_t io_buffer_size; QEMUSGList sg; /* PIO transfer handling */ diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 893c9b9bae..3ee962f830 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -286,7 +286,11 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) return; done: - block_acct_done(blk_get_stats(s->blk), &s->acct); + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { + block_acct_done(blk_get_stats(s->blk), &s->acct); + } io->dma_end(opaque); return; @@ -348,7 +352,11 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) done: if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { - block_acct_done(blk_get_stats(s->blk), &s->acct); + if (ret < 0) { + block_acct_failed(blk_get_stats(s->blk), &s->acct); + } else { + block_acct_done(blk_get_stats(s->blk), &s->acct); + } } io->dma_end(opaque); } diff --git a/hw/ide/pci.c b/hw/ide/pci.c index d31ff885b7..9c54b378d6 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -103,13 +103,6 @@ static int32_t bmdma_prepare_buf(IDEDMA *dma, int32_t limit) qemu_sglist_add(&s->sg, bm->cur_prd_addr, sg_len); } - /* Note: We limit the max transfer to be 2GiB. - * This should accommodate the largest ATA transaction - * for LBA48 (65,536 sectors) and 32K sector sizes. */ - if (s->sg.size > INT32_MAX) { - error_report("IDE: sglist describes more than 2GiB."); - break; - } bm->cur_prd_addr += l; bm->cur_prd_len -= l; s->io_buffer_size += l; |