diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index d026242e2b..68956aeb94 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -56,6 +56,16 @@ #define FTGMAC100_PHYDATA 0x64 #define FTGMAC100_FCR 0x68 +/* + * FTGMAC100 registers high + * + * values below are offset by - FTGMAC100_REG_HIGH_OFFSET from datasheet + * because its memory region is start at FTGMAC100_REG_HIGH_OFFSET + */ +#define FTGMAC100_NPTXR_BADR_HIGH (0x17C - FTGMAC100_REG_HIGH_OFFSET) +#define FTGMAC100_HPTXR_BADR_HIGH (0x184 - FTGMAC100_REG_HIGH_OFFSET) +#define FTGMAC100_RXR_BADR_HIGH (0x18C - FTGMAC100_REG_HIGH_OFFSET) + /* * Interrupt status register & interrupt enable register */ @@ -913,6 +923,60 @@ static void ftgmac100_write(void *opaque, hwaddr addr, ftgmac100_update_irq(s); } +static uint64_t ftgmac100_high_read(void *opaque, hwaddr addr, unsigned size) +{ + FTGMAC100State *s = FTGMAC100(opaque); + uint64_t val = 0; + + switch (addr) { + case FTGMAC100_NPTXR_BADR_HIGH: + val = extract64(s->tx_ring, 32, 32); + break; + case FTGMAC100_HPTXR_BADR_HIGH: + /* High Priority Transmit Ring Base High Address */ + qemu_log_mask(LOG_UNIMP, "%s: read to unimplemented register 0x%" + HWADDR_PRIx "\n", __func__, addr); + break; + case FTGMAC100_RXR_BADR_HIGH: + val = extract64(s->rx_ring, 32, 32); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset 0x%" + HWADDR_PRIx "\n", __func__, addr); + break; + } + + return val; +} + +static void ftgmac100_high_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + FTGMAC100State *s = FTGMAC100(opaque); + + switch (addr) { + case FTGMAC100_NPTXR_BADR_HIGH: + s->tx_ring = deposit64(s->tx_ring, 32, 32, value); + s->tx_descriptor = deposit64(s->tx_descriptor, 32, 32, value); + break; + case FTGMAC100_HPTXR_BADR_HIGH: + /* High Priority Transmit Ring Base High Address */ + qemu_log_mask(LOG_UNIMP, "%s: write to unimplemented register 0x%" + HWADDR_PRIx "\n", __func__, addr); + break; + case FTGMAC100_RXR_BADR_HIGH: + s->rx_ring = deposit64(s->rx_ring, 32, 32, value); + s->rx_descriptor = deposit64(s->rx_descriptor, 32, 32, value); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset 0x%" + HWADDR_PRIx "\n", __func__, addr); + break; + } + + ftgmac100_update_irq(s); +} + static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len) { unsigned mcast_idx; @@ -1077,6 +1141,14 @@ static const MemoryRegionOps ftgmac100_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static const MemoryRegionOps ftgmac100_high_ops = { + .read = ftgmac100_high_read, + .write = ftgmac100_high_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static void ftgmac100_cleanup(NetClientState *nc) { FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc)); @@ -1114,6 +1186,15 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) TYPE_FTGMAC100 ".regs", FTGMAC100_REG_MEM_SIZE); memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem); + if (s->dma64) { + memory_region_init_io(&s->iomem_high, OBJECT(s), &ftgmac100_high_ops, + s, TYPE_FTGMAC100 ".regs.high", + FTGMAC100_REG_HIGH_MEM_SIZE); + memory_region_add_subregion(&s->iomem_container, + FTGMAC100_REG_HIGH_OFFSET, + &s->iomem_high); + } + sysbus_init_irq(sbd, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); @@ -1162,6 +1243,7 @@ static const VMStateDescription vmstate_ftgmac100 = { static Property ftgmac100_properties[] = { DEFINE_PROP_BOOL("aspeed", FTGMAC100State, aspeed, false), DEFINE_NIC_PROPERTIES(FTGMAC100State, conf), + DEFINE_PROP_BOOL("dma64", FTGMAC100State, dma64, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h index aae57ae8cb..24ccdf0260 100644 --- a/include/hw/net/ftgmac100.h +++ b/include/hw/net/ftgmac100.h @@ -16,6 +16,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(FTGMAC100State, FTGMAC100) #define FTGMAC100_MEM_SIZE 0x1000 #define FTGMAC100_REG_MEM_SIZE 0x100 +#define FTGMAC100_REG_HIGH_MEM_SIZE 0x100 +#define FTGMAC100_REG_HIGH_OFFSET 0x100 #include "hw/sysbus.h" #include "net/net.h" @@ -35,6 +37,7 @@ struct FTGMAC100State { qemu_irq irq; MemoryRegion iomem_container; MemoryRegion iomem; + MemoryRegion iomem_high; uint8_t frame[FTGMAC100_MAX_FRAME_SIZE]; @@ -68,6 +71,7 @@ struct FTGMAC100State { bool aspeed; uint32_t txdes0_edotr; uint32_t rxdes0_edorr; + bool dma64; }; #define TYPE_ASPEED_MII "aspeed-mmi"