mirror of https://gitee.com/openkylin/qemu.git
hw/lan9118: Add basic 16-bit mode support.
Signed-off-by: Evgeny Voevodin <e.voevodin@samsung.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
12c775db14
commit
1248f8d4cb
124
hw/lan9118.c
124
hw/lan9118.c
|
@ -235,11 +235,21 @@ typedef struct {
|
|||
int32_t rxp_offset;
|
||||
int32_t rxp_size;
|
||||
int32_t rxp_pad;
|
||||
|
||||
uint32_t write_word_prev_offset;
|
||||
uint32_t write_word_n;
|
||||
uint16_t write_word_l;
|
||||
uint16_t write_word_h;
|
||||
uint32_t read_word_prev_offset;
|
||||
uint32_t read_word_n;
|
||||
uint32_t read_long;
|
||||
|
||||
uint32_t mode_16bit;
|
||||
} lan9118_state;
|
||||
|
||||
static const VMStateDescription vmstate_lan9118 = {
|
||||
.name = "lan9118",
|
||||
.version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_PTIMER(timer, lan9118_state),
|
||||
|
@ -294,6 +304,14 @@ static const VMStateDescription vmstate_lan9118 = {
|
|||
VMSTATE_INT32(rxp_offset, lan9118_state),
|
||||
VMSTATE_INT32(rxp_size, lan9118_state),
|
||||
VMSTATE_INT32(rxp_pad, lan9118_state),
|
||||
VMSTATE_UINT32_V(write_word_prev_offset, lan9118_state, 2),
|
||||
VMSTATE_UINT32_V(write_word_n, lan9118_state, 2),
|
||||
VMSTATE_UINT16_V(write_word_l, lan9118_state, 2),
|
||||
VMSTATE_UINT16_V(write_word_h, lan9118_state, 2),
|
||||
VMSTATE_UINT32_V(read_word_prev_offset, lan9118_state, 2),
|
||||
VMSTATE_UINT32_V(read_word_n, lan9118_state, 2),
|
||||
VMSTATE_UINT32_V(read_long, lan9118_state, 2),
|
||||
VMSTATE_UINT32_V(mode_16bit, lan9118_state, 2),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
@ -390,7 +408,7 @@ static void lan9118_reset(DeviceState *d)
|
|||
s->fifo_int = 0x48000000;
|
||||
s->rx_cfg = 0;
|
||||
s->tx_cfg = 0;
|
||||
s->hw_cfg = 0x00050000;
|
||||
s->hw_cfg = s->mode_16bit ? 0x00050000 : 0x00050004;
|
||||
s->pmt_ctrl &= 0x45;
|
||||
s->gpio_cfg = 0;
|
||||
s->txp->fifo_used = 0;
|
||||
|
@ -429,6 +447,9 @@ static void lan9118_reset(DeviceState *d)
|
|||
s->mac_mii_data = 0;
|
||||
s->mac_flow = 0;
|
||||
|
||||
s->read_word_n = 0;
|
||||
s->write_word_n = 0;
|
||||
|
||||
phy_reset(s);
|
||||
|
||||
s->eeprom_writable = 0;
|
||||
|
@ -984,7 +1005,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
|
|||
{
|
||||
lan9118_state *s = (lan9118_state *)opaque;
|
||||
offset &= 0xff;
|
||||
|
||||
|
||||
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
|
||||
if (offset >= 0x20 && offset < 0x40) {
|
||||
/* TX FIFO */
|
||||
|
@ -1034,7 +1055,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
|
|||
/* SRST */
|
||||
lan9118_reset(&s->busdev.qdev);
|
||||
} else {
|
||||
s->hw_cfg = val & 0x003f300;
|
||||
s->hw_cfg = (val & 0x003f300) | (s->hw_cfg & 0x4);
|
||||
}
|
||||
break;
|
||||
case CSR_RX_DP_CTRL:
|
||||
|
@ -1113,6 +1134,46 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
|
|||
lan9118_update(s);
|
||||
}
|
||||
|
||||
static void lan9118_writew(void *opaque, target_phys_addr_t offset,
|
||||
uint32_t val)
|
||||
{
|
||||
lan9118_state *s = (lan9118_state *)opaque;
|
||||
offset &= 0xff;
|
||||
|
||||
if (s->write_word_prev_offset != (offset & ~0x3)) {
|
||||
/* New offset, reset word counter */
|
||||
s->write_word_n = 0;
|
||||
s->write_word_prev_offset = offset & ~0x3;
|
||||
}
|
||||
|
||||
if (offset & 0x2) {
|
||||
s->write_word_h = val;
|
||||
} else {
|
||||
s->write_word_l = val;
|
||||
}
|
||||
|
||||
//DPRINTF("Writew reg 0x%02x = 0x%08x\n", (int)offset, val);
|
||||
s->write_word_n++;
|
||||
if (s->write_word_n == 2) {
|
||||
s->write_word_n = 0;
|
||||
lan9118_writel(s, offset & ~3, s->write_word_l +
|
||||
(s->write_word_h << 16), 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void lan9118_16bit_mode_write(void *opaque, target_phys_addr_t offset,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
switch (size) {
|
||||
case 2:
|
||||
return lan9118_writew(opaque, offset, (uint32_t)val);
|
||||
case 4:
|
||||
return lan9118_writel(opaque, offset, val, size);
|
||||
}
|
||||
|
||||
hw_error("lan9118_write: Bad size 0x%x\n", size);
|
||||
}
|
||||
|
||||
static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
|
||||
unsigned size)
|
||||
{
|
||||
|
@ -1149,7 +1210,7 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
|
|||
case CSR_TX_CFG:
|
||||
return s->tx_cfg;
|
||||
case CSR_HW_CFG:
|
||||
return s->hw_cfg | 0x4;
|
||||
return s->hw_cfg;
|
||||
case CSR_RX_DP_CTRL:
|
||||
return 0;
|
||||
case CSR_RX_FIFO_INF:
|
||||
|
@ -1187,12 +1248,60 @@ static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t lan9118_readw(void *opaque, target_phys_addr_t offset)
|
||||
{
|
||||
lan9118_state *s = (lan9118_state *)opaque;
|
||||
uint32_t val;
|
||||
|
||||
if (s->read_word_prev_offset != (offset & ~0x3)) {
|
||||
/* New offset, reset word counter */
|
||||
s->read_word_n = 0;
|
||||
s->read_word_prev_offset = offset & ~0x3;
|
||||
}
|
||||
|
||||
s->read_word_n++;
|
||||
if (s->read_word_n == 1) {
|
||||
s->read_long = lan9118_readl(s, offset & ~3, 4);
|
||||
} else {
|
||||
s->read_word_n = 0;
|
||||
}
|
||||
|
||||
if (offset & 2) {
|
||||
val = s->read_long >> 16;
|
||||
} else {
|
||||
val = s->read_long & 0xFFFF;
|
||||
}
|
||||
|
||||
//DPRINTF("Readw reg 0x%02x, val 0x%x\n", (int)offset, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint64_t lan9118_16bit_mode_read(void *opaque, target_phys_addr_t offset,
|
||||
unsigned size)
|
||||
{
|
||||
switch (size) {
|
||||
case 2:
|
||||
return lan9118_readw(opaque, offset);
|
||||
case 4:
|
||||
return lan9118_readl(opaque, offset, size);
|
||||
}
|
||||
|
||||
hw_error("lan9118_read: Bad size 0x%x\n", size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps lan9118_mem_ops = {
|
||||
.read = lan9118_readl,
|
||||
.write = lan9118_writel,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps lan9118_16bit_mem_ops = {
|
||||
.read = lan9118_16bit_mode_read,
|
||||
.write = lan9118_16bit_mode_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void lan9118_cleanup(VLANClientState *nc)
|
||||
{
|
||||
lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
|
||||
|
@ -1214,8 +1323,10 @@ static int lan9118_init1(SysBusDevice *dev)
|
|||
lan9118_state *s = FROM_SYSBUS(lan9118_state, dev);
|
||||
QEMUBH *bh;
|
||||
int i;
|
||||
const MemoryRegionOps *mem_ops =
|
||||
s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
|
||||
|
||||
memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100);
|
||||
memory_region_init_io(&s->mmio, mem_ops, s, "lan9118-mmio", 0x100);
|
||||
sysbus_init_mmio(dev, &s->mmio);
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
||||
|
@ -1240,6 +1351,7 @@ static int lan9118_init1(SysBusDevice *dev)
|
|||
|
||||
static Property lan9118_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(lan9118_state, conf),
|
||||
DEFINE_PROP_UINT32("mode_16bit", lan9118_state, mode_16bit, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue