From 9fbf0fa81fca8f527669dd4fa72662d66e7d6329 Mon Sep 17 00:00:00 2001 From: John Snow Date: Fri, 6 Nov 2015 14:09:00 -0500 Subject: [PATCH 1/5] ide: remove hardcoded 2GiB transactional limit Not that you can request a >2GiB transaction, but that's why checking for it makes no sense anymore. With the newer 'limit' parameter to prepare_buf, we no longer need a static limit. The maximum limit is still 2GiB, but the limit parameter is set to the current transaction size, which cannot surpass 32MiB (512 * 65536). If the PRDT surpasses the transactional size, then, we'll just carry out the normative underflow handling pathways instead of needing an extra, strange pathway that worries about hitting some logistical cap for the largest sglist we can support -- we'll never even attempt to build one that big anymore. Reported-by: Kevin Wolf Signed-off-by: John Snow Acked-by: Stefan Hajnoczi Message-id: 1445902682-20051-1-git-send-email-jsnow@redhat.com --- hw/ide/ahci.c | 30 ++++++++++++++---------------- hw/ide/internal.h | 2 +- hw/ide/pci.c | 7 ------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 21f76ed86e..f547ebb46c 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -804,8 +804,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 +836,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 +885,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; - } } } 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/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; From 802742670df73773c0dbaa251c63e4561cc794a1 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 6 Nov 2015 14:09:00 -0500 Subject: [PATCH 2/5] ahci: Add some MMIO debug printfs These are useful for bringup of AHCI. Signed-off-by: Peter Crosthwaite Reviewed-by: John Snow Message-id: 517ba413dce7deb4ab17c0cc1e8bbdaaace2a0db.1445917756.git.crosthwaite.peter@gmail.com Signed-off-by: John Snow --- hw/ide/ahci.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index f547ebb46c..721918991c 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); - } - g_assert_cmpint(size, >, 1); + 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); - return (hi << 32 | lo) >> (ofst * 8); + /* 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); + } + + 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" From 0487eea48ecc6e525d6e626d94da54e203089a95 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 6 Nov 2015 14:09:00 -0500 Subject: [PATCH 3/5] ahci: split realize and init Do the init level tasks asap and the realize later (mainly when num_ports is available). This allows sub-class realize routines to work with the device post-init. Signed-off-by: Peter Crosthwaite Reviewed-by: John Snow Message-id: 1a7c7b2b32e5ccf49373a5065da5ece89730d3ac.1445917756.git.crosthwaite.peter@gmail.com Signed-off-by: John Snow --- hw/ide/ahci.c | 36 +++++++++++++++++++++++------------- hw/ide/ahci.h | 3 ++- hw/ide/ich.c | 10 +++++++++- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 721918991c..a3a182bd37 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1434,7 +1434,17 @@ 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) +{ + s->container = qdev; + /* 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); +} + +void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) { qemu_irq *irqs; int i; @@ -1442,16 +1452,8 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) 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); - for (i = 0; i < s->ports; i++) { AHCIDevice *ad = &s->dev[i]; @@ -1646,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(), @@ -1677,6 +1686,7 @@ 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, }; diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index c9b3805415..4ccaf5d819 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); 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, }; From 377e2145392e5787d35e58d643bd3de4838006b4 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 6 Nov 2015 14:09:01 -0500 Subject: [PATCH 4/5] ahci: Add allwinner AHCI Add a Sysbus AHCI subclass for the Allwinner AHCI. It has a few extra vendor specific registers which are used for phy and power init. Signed-off-by: Peter Crosthwaite Reviewed-by: John Snow Message-id: 833b5b05ed5ade38bf69656679b0a7575e79492b.1445917756.git.crosthwaite.peter@gmail.com [resolved patch context on pull --js] Signed-off-by: John Snow --- hw/ide/ahci.c | 95 +++++++++++++++++++++++++++++++++++++++++ hw/ide/ahci.h | 16 +++++++ include/qemu/typedefs.h | 1 + 3 files changed, 112 insertions(+) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index a3a182bd37..dd1912e80d 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1690,9 +1690,104 @@ static const TypeInfo sysbus_ahci_info = { .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 4ccaf5d819..bc777ed5c2 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -386,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/include/qemu/typedefs.h b/include/qemu/typedefs.h index d961362d36..2cdce1866e 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -9,6 +9,7 @@ struct Monitor; typedef struct AdapterInfo AdapterInfo; typedef struct AddressSpace AddressSpace; typedef struct AioContext AioContext; +typedef struct AllwinnerAHCIState AllwinnerAHCIState; typedef struct AudioState AudioState; typedef struct BlockBackend BlockBackend; typedef struct BlockBackendRootState BlockBackendRootState; From dca625768a7da9377cd5886cc03854229c1e18a1 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Fri, 6 Nov 2015 14:09:01 -0500 Subject: [PATCH 5/5] arm: allwinner-a10: Add SATA Add the Allwinner A10 AHCI controller module to the SoC. Signed-off-by: Peter Crosthwaite Reviewed-by: John Snow Message-id: 69d6962f2d14a218bd07e9ac4ccd1947737cc30f.1445917756.git.crosthwaite.peter@gmail.com Signed-off-by: John Snow --- hw/arm/allwinner-a10.c | 11 +++++++++++ include/hw/arm/allwinner-a10.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index 43dc0a12de..b0ca81cea3 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -39,6 +39,9 @@ static void aw_a10_init(Object *obj) qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC); qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); } + + object_initialize(&s->sata, sizeof(s->sata), TYPE_ALLWINNER_AHCI); + qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default()); } static void aw_a10_realize(DeviceState *dev, Error **errp) @@ -93,6 +96,14 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(sysbusdev, 0, AW_A10_EMAC_BASE); sysbus_connect_irq(sysbusdev, 0, s->irq[55]); + object_property_set_bool(OBJECT(&s->sata), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, AW_A10_SATA_BASE); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, s->irq[56]); + /* FIXME use a qdev chardev prop instead of serial_hds[] */ serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, s->irq[1], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h index 01a189bcdc..6b32a99e21 100644 --- a/include/hw/arm/allwinner-a10.h +++ b/include/hw/arm/allwinner-a10.h @@ -7,6 +7,8 @@ #include "hw/timer/allwinner-a10-pit.h" #include "hw/intc/allwinner-a10-pic.h" #include "hw/net/allwinner_emac.h" +#include "hw/ide/pci.h" +#include "hw/ide/ahci.h" #include "sysemu/sysemu.h" #include "exec/address-spaces.h" @@ -16,6 +18,7 @@ #define AW_A10_PIT_REG_BASE 0x01c20c00 #define AW_A10_UART0_REG_BASE 0x01c28000 #define AW_A10_EMAC_BASE 0x01c0b000 +#define AW_A10_SATA_BASE 0x01c18000 #define AW_A10_SDRAM_BASE 0x40000000 @@ -32,6 +35,7 @@ typedef struct AwA10State { AwA10PITState timer; AwA10PICState intc; AwEmacState emac; + AllwinnerAHCIState sata; } AwA10State; #define ALLWINNER_H_