From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34284) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b3EdT-00061d-Ug for qemu-devel@nongnu.org; Wed, 18 May 2016 23:28:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b3EdN-00058h-SG for qemu-devel@nongnu.org; Wed, 18 May 2016 23:28:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38411) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b3EdN-00057O-EA for qemu-devel@nongnu.org; Wed, 18 May 2016 23:28:25 -0400 References: <2340f45a659a3f9a17307eaba0f44f9ebfdc62c3.1463609668.git.jcd@tribudubois.net> From: Jason Wang Message-ID: <573D32C2.20609@redhat.com> Date: Thu, 19 May 2016 11:28:02 +0800 MIME-Version: 1.0 In-Reply-To: <2340f45a659a3f9a17307eaba0f44f9ebfdc62c3.1463609668.git.jcd@tribudubois.net> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v4 6/8] i.MX: move FEC device to a register array structure. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Jean-Christophe Dubois , qemu-devel@nongnu.org, peter.maydell@linaro.org On 2016=E5=B9=B405=E6=9C=8819=E6=97=A5 06:23, Jean-Christophe Dubois wrot= e: > This is to prepare for the ENET Gb device of the i.MX6. > > Signed-off-by: Jean-Christophe Dubois > --- > > Changes since v1: > * Not present on v1. > > Changes since v2: > * The patch was split in 2 parts: > - a "port" to a reg array based device (this patch). > - the addition of the Gb support (next patch). > =20 > Changes since v3: > * Small fix patches were extracted from this patch (see previous 3 pa= tches) > * Reset logic through ECR was fixed. > * TDAR/RDAR behavior was fixed. > > hw/net/imx_fec.c | 396 ++++++++++++++++++++++++++------------= --------- > include/hw/net/imx_fec.h | 55 ++++--- > 2 files changed, 258 insertions(+), 193 deletions(-) > > diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c > index 87e3c87..565b4a3 100644 > --- a/hw/net/imx_fec.c > +++ b/hw/net/imx_fec.c > @@ -52,30 +52,75 @@ > } \ > } while (0) > =20 > +static const char *imx_fec_reg_name(IMXFECState *s, uint32_t index) > +{ > + static char tmp[20]; > + > + switch (index) { > + case ENET_EIR: > + return "EIR"; > + case ENET_EIMR: > + return "EIMR"; > + case ENET_RDAR: > + return "RDAR"; > + case ENET_TDAR: > + return "TDAR"; > + case ENET_ECR: > + return "ECR"; > + case ENET_MMFR: > + return "MMFR"; > + case ENET_MSCR: > + return "MSCR"; > + case ENET_MIBC: > + return "MIBC"; > + case ENET_RCR: > + return "RCR"; > + case ENET_TCR: > + return "TCR"; > + case ENET_PALR: > + return "PALR"; > + case ENET_PAUR: > + return "PAUR"; > + case ENET_OPD: > + return "OPD"; > + case ENET_IAUR: > + return "IAUR"; > + case ENET_IALR: > + return "IALR"; > + case ENET_GAUR: > + return "GAUR"; > + case ENET_GALR: > + return "GALR"; > + case ENET_TFWR: > + return "TFWR"; > + case ENET_RDSR: > + return "RDSR"; > + case ENET_TDSR: > + return "TDSR"; > + case ENET_MRBR: > + return "MRBR"; > + case ENET_FRBR: > + return "FRBR"; > + case ENET_FRSR: > + return "FRSR"; > + case ENET_MIIGSK_CFGR: > + return "MIIGSK_CFGR"; > + case ENET_MIIGSK_ENR: > + return "MIIGSK_ENR"; > + default: > + sprintf(tmp, "index %d", index); > + return tmp; > + } > +} > + > static const VMStateDescription vmstate_imx_fec =3D { > .name =3D TYPE_IMX_FEC, > - .version_id =3D 1, > - .minimum_version_id =3D 1, > + .version_id =3D 2, > + .minimum_version_id =3D 2, > .fields =3D (VMStateField[]) { > - VMSTATE_UINT32(irq_state, IMXFECState), > - VMSTATE_UINT32(eir, IMXFECState), > - VMSTATE_UINT32(eimr, IMXFECState), > - VMSTATE_UINT32(rx_enabled, IMXFECState), > + VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX), > VMSTATE_UINT32(rx_descriptor, IMXFECState), > VMSTATE_UINT32(tx_descriptor, IMXFECState), > - VMSTATE_UINT32(ecr, IMXFECState), > - VMSTATE_UINT32(mmfr, IMXFECState), > - VMSTATE_UINT32(mscr, IMXFECState), > - VMSTATE_UINT32(mibc, IMXFECState), > - VMSTATE_UINT32(rcr, IMXFECState), > - VMSTATE_UINT32(tcr, IMXFECState), > - VMSTATE_UINT32(tfwr, IMXFECState), > - VMSTATE_UINT32(frsr, IMXFECState), > - VMSTATE_UINT32(erdsr, IMXFECState), > - VMSTATE_UINT32(etdsr, IMXFECState), > - VMSTATE_UINT32(emrbr, IMXFECState), > - VMSTATE_UINT32(miigsk_cfgr, IMXFECState), > - VMSTATE_UINT32(miigsk_enr, IMXFECState), > =20 > VMSTATE_UINT32(phy_status, IMXFECState), > VMSTATE_UINT32(phy_control, IMXFECState), > @@ -251,15 +296,13 @@ static void imx_fec_write_bd(IMXFECBufDesc *bd, d= ma_addr_t addr) > =20 > static void imx_fec_update(IMXFECState *s) > { > - uint32_t active; > - uint32_t changed; > - > - active =3D s->eir & s->eimr; > - changed =3D active ^ s->irq_state; > - if (changed) { > - qemu_set_irq(s->irq, active); > + if (s->regs[ENET_EIR] & s->regs[ENET_EIMR]) { > + FEC_PRINTF("interrupt raised\n"); > + qemu_set_irq(s->irq, 1); > + } else { > + FEC_PRINTF("interrupt lowered\n"); > + qemu_set_irq(s->irq, 0); > } > - s->irq_state =3D active; > } > =20 > static void imx_fec_do_tx(IMXFECState *s) > @@ -283,7 +326,7 @@ static void imx_fec_do_tx(IMXFECState *s) > len =3D bd.length; > if (frame_size + len > FEC_MAX_FRAME_SIZE) { > len =3D FEC_MAX_FRAME_SIZE - frame_size; > - s->eir |=3D FEC_INT_BABT; > + s->regs[ENET_EIR] |=3D FEC_INT_BABT; > } > dma_memory_read(&address_space_memory, bd.data, ptr, len); > ptr +=3D len; > @@ -293,17 +336,17 @@ static void imx_fec_do_tx(IMXFECState *s) > qemu_send_packet(qemu_get_queue(s->nic), frame, len); > ptr =3D frame; > frame_size =3D 0; > - s->eir |=3D FEC_INT_TXF; > + s->regs[ENET_EIR] |=3D FEC_INT_TXF; > } > - s->eir |=3D FEC_INT_TXB; > + s->regs[ENET_EIR] |=3D FEC_INT_TXB; > bd.flags &=3D ~FEC_BD_R; > /* Write back the modified descriptor. */ > imx_fec_write_bd(&bd, addr); > /* Advance to the next descriptor. */ > if ((bd.flags & FEC_BD_W) !=3D 0) { > - addr =3D s->etdsr; > + addr =3D s->regs[ENET_TDSR]; > } else { > - addr +=3D 8; > + addr +=3D sizeof(bd); > } > } > =20 > @@ -315,7 +358,7 @@ static void imx_fec_do_tx(IMXFECState *s) > static void imx_fec_enable_rx(IMXFECState *s) > { > IMXFECBufDesc bd; > - uint32_t tmp; > + bool tmp; > =20 > imx_fec_read_bd(&bd, s->rx_descriptor); > =20 > @@ -323,11 +366,11 @@ static void imx_fec_enable_rx(IMXFECState *s) > =20 > if (!tmp) { > FEC_PRINTF("RX buffer full\n"); > - } else if (!s->rx_enabled) { > + } else if (!s->regs[ENET_RDAR]) { > qemu_flush_queued_packets(qemu_get_queue(s->nic)); > } > =20 > - s->rx_enabled =3D tmp; > + s->regs[ENET_RDAR] =3D tmp ? ENET_RDAR_RDAR : 0; > } > =20 > static void imx_fec_reset(DeviceState *d) > @@ -335,18 +378,26 @@ static void imx_fec_reset(DeviceState *d) > IMXFECState *s =3D IMX_FEC(d); > =20 > /* Reset the FEC */ > - s->eir =3D 0; > - s->eimr =3D 0; > - s->rx_enabled =3D 0; > - s->ecr =3D 0xf0000000; > - s->mscr =3D 0; > - s->mibc =3D 0xc0000000; > - s->rcr =3D 0x05ee0001; > - s->tcr =3D 0; > - s->tfwr =3D 0; > - s->frsr =3D 0x500; > - s->miigsk_cfgr =3D 0; > - s->miigsk_enr =3D 0x6; > + memset(s->regs, 0, sizeof(s->regs)); > + s->regs[ENET_ECR] =3D 0xf0000000; > + s->regs[ENET_MIBC] =3D 0xc0000000; > + s->regs[ENET_RCR] =3D 0x05ee0001; > + s->regs[ENET_OPD] =3D 0x00010000; > + > + s->regs[ENET_PALR] =3D (s->conf.macaddr.a[0] << 24) > + | (s->conf.macaddr.a[1] << 16) > + | (s->conf.macaddr.a[2] << 8) > + | s->conf.macaddr.a[3]; > + s->regs[ENET_PAUR] =3D (s->conf.macaddr.a[4] << 24) > + | (s->conf.macaddr.a[5] << 16) > + | 0x8808; > + > + s->regs[ENET_FRBR] =3D 0x00000600; > + s->regs[ENET_FRSR] =3D 0x00000500; > + s->regs[ENET_MIIGSK_ENR] =3D 0x00000006; > + > + s->rx_descriptor =3D 0; > + s->tx_descriptor =3D 0; > =20 > /* We also reset the PHY */ > phy_reset(s); > @@ -354,183 +405,180 @@ static void imx_fec_reset(DeviceState *d) > =20 > static uint64_t imx_fec_read(void *opaque, hwaddr addr, unsigned size= ) > { > + uint32_t value =3D 0; > IMXFECState *s =3D IMX_FEC(opaque); > - > - FEC_PRINTF("reading from @ 0x%" HWADDR_PRIx "\n", addr); > - > - switch (addr & 0x3ff) { > - case 0x004: > - return s->eir; > - case 0x008: > - return s->eimr; > - case 0x010: > - return s->rx_enabled ? (1 << 24) : 0; /* RDAR */ > - case 0x014: > - return 0; /* TDAR */ > - case 0x024: > - return s->ecr; > - case 0x040: > - return s->mmfr; > - case 0x044: > - return s->mscr; > - case 0x064: > - return s->mibc; /* MIBC */ > - case 0x084: > - return s->rcr; > - case 0x0c4: > - return s->tcr; > - case 0x0e4: /* PALR */ > - return (s->conf.macaddr.a[0] << 24) > - | (s->conf.macaddr.a[1] << 16) > - | (s->conf.macaddr.a[2] << 8) > - | s->conf.macaddr.a[3]; > - break; > - case 0x0e8: /* PAUR */ > - return (s->conf.macaddr.a[4] << 24) > - | (s->conf.macaddr.a[5] << 16) > - | 0x8808; > - case 0x0ec: > - return 0x10000; /* OPD */ > - case 0x118: > - return 0; > - case 0x11c: > - return 0; > - case 0x120: > - return 0; > - case 0x124: > - return 0; > - case 0x144: > - return s->tfwr; > - case 0x14c: > - return 0x600; > - case 0x150: > - return s->frsr; > - case 0x180: > - return s->erdsr; > - case 0x184: > - return s->etdsr; > - case 0x188: > - return s->emrbr; > - case 0x300: > - return s->miigsk_cfgr; > - case 0x308: > - return s->miigsk_enr; > + uint32_t index =3D addr >> 2; > + > + switch (index) { > + case ENET_EIR: > + case ENET_EIMR: > + case ENET_RDAR: > + case ENET_TDAR: > + case ENET_ECR: > + case ENET_MMFR: > + case ENET_MSCR: > + case ENET_MIBC: > + case ENET_RCR: > + case ENET_TCR: > + case ENET_PALR: > + case ENET_PAUR: > + case ENET_OPD: > + case ENET_IAUR: > + case ENET_IALR: > + case ENET_GAUR: > + case ENET_GALR: > + case ENET_TFWR: > + case ENET_RDSR: > + case ENET_TDSR: > + case ENET_MRBR: > + case ENET_FRBR: > + case ENET_FRSR: > + case ENET_MIIGSK_CFGR: > + case ENET_MIIGSK_ENR: > + value =3D s->regs[index]; > + break; > default: > - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset = 0x%" > - HWADDR_PRIx "\n", TYPE_IMX_FEC, __func__, addr); > - return 0; > + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset= 0x%" > + PRIx32 "\n", TYPE_IMX_FEC, __func__, index * 4); > + break; > } > + > + FEC_PRINTF("reg[%s] =3D> 0x%" PRIx32 "\n", imx_fec_reg_name(s, ind= ex), > + value); > + > + return value; > } > =20 > static void imx_fec_write(void *opaque, hwaddr addr, > uint64_t value, unsigned size) > { > IMXFECState *s =3D IMX_FEC(opaque); > + uint32_t index =3D addr >> 2; > =20 > - FEC_PRINTF("writing 0x%08x @ 0x%" HWADDR_PRIx "\n", (int)value, ad= dr); > + FEC_PRINTF("reg[%s] <=3D 0x%" PRIx32 "\n", imx_fec_reg_name(s, ind= ex), > + (uint32_t)value); > =20 > - switch (addr & 0x3ff) { > - case 0x004: /* EIR */ > - s->eir &=3D ~value; > + switch (index) { > + case ENET_EIR: > + s->regs[index] &=3D ~value; > break; > - case 0x008: /* EIMR */ > - s->eimr =3D value; > + case ENET_EIMR: > + s->regs[index] =3D value; > break; > - case 0x010: /* RDAR */ > - if ((s->ecr & FEC_EN) && !s->rx_enabled) { > - imx_fec_enable_rx(s); > + case ENET_RDAR: > + if (s->regs[ENET_ECR] & FEC_EN) { > + if (!s->regs[index]) { > + s->regs[index] =3D ENET_RDAR_RDAR; > + imx_fec_enable_rx(s); > + } > + } else { > + s->regs[index] =3D 0; > } > break; > - case 0x014: /* TDAR */ > - if (s->ecr & FEC_EN) { > + case ENET_TDAR: > + if (s->regs[ENET_ECR] & FEC_EN) { > + s->regs[index] =3D ENET_TDAR_TDAR; > imx_fec_do_tx(s); > } > + s->regs[index] =3D 0; > break; > - case 0x024: /* ECR */ > - s->ecr =3D value; > + case ENET_ECR: > if (value & FEC_RESET) { > - imx_fec_reset(DEVICE(s)); > + return imx_fec_reset(DEVICE(s)); > } > - if ((s->ecr & FEC_EN) =3D=3D 0) { > - s->rx_enabled =3D 0; > + s->regs[index] =3D value; > + if ((s->regs[index] & FEC_EN) =3D=3D 0) { > + s->regs[ENET_RDAR] =3D 0; > + s->rx_descriptor =3D s->regs[ENET_RDSR]; > + s->regs[ENET_TDAR] =3D 0; > + s->tx_descriptor =3D s->regs[ENET_TDSR]; This seems like a new behavior, is this a bug fix? If yes, better split. > } > break; > - case 0x040: /* MMFR */ > - /* store the value */ > - s->mmfr =3D value; > + case ENET_MMFR: > + s->regs[index] =3D value; > if (extract32(value, 29, 1)) { > - s->mmfr =3D do_phy_read(s, extract32(value, 18, 10)); > + /* This is a read operation */ > + s->regs[ENET_MMFR] =3D deposit32(s->regs[ENET_MMFR], 0, 16= , > + do_phy_read(s, > + extract32(value= , > + 18, 1= 0))); > } else { > + /* This a write operation */ > do_phy_write(s, extract32(value, 18, 10), extract32(value= , 0, 16)); > } > /* raise the interrupt as the PHY operation is done */ > - s->eir |=3D FEC_INT_MII; > + s->regs[ENET_EIR] |=3D FEC_INT_MII; > break; > - case 0x044: /* MSCR */ > - s->mscr =3D value & 0xfe; > + case ENET_MSCR: > + s->regs[index] =3D value & 0xfe; > break; > - case 0x064: /* MIBC */ > + case ENET_MIBC: > /* TODO: Implement MIB. */ > - s->mibc =3D (value & 0x80000000) ? 0xc0000000 : 0; > + s->regs[index] =3D (value & 0x80000000) ? 0xc0000000 : 0; > break; > - case 0x084: /* RCR */ > - s->rcr =3D value & 0x07ff003f; > + case ENET_RCR: > + s->regs[index] =3D value & 0x07ff003f; > /* TODO: Implement LOOP mode. */ > break; > - case 0x0c4: /* TCR */ > + case ENET_TCR: > /* We transmit immediately, so raise GRA immediately. */ > - s->tcr =3D value; > + s->regs[index] =3D value; > if (value & 1) { > - s->eir |=3D FEC_INT_GRA; > + s->regs[ENET_EIR] |=3D FEC_INT_GRA; > } > break; > - case 0x0e4: /* PALR */ > + case ENET_PALR: > + s->regs[index] =3D value; > s->conf.macaddr.a[0] =3D value >> 24; > s->conf.macaddr.a[1] =3D value >> 16; > s->conf.macaddr.a[2] =3D value >> 8; > s->conf.macaddr.a[3] =3D value; I believe we should use stl_be_p() here? > break; > - case 0x0e8: /* PAUR */ > + case ENET_PAUR: > + s->regs[index] =3D (value | 0x0000ffff) & 0xffff8808; > s->conf.macaddr.a[4] =3D value >> 24; > s->conf.macaddr.a[5] =3D value >> 16; > break; > - case 0x0ec: /* OPDR */ > + case ENET_OPD: > + s->regs[index] =3D (value & 0x0000ffff) | 0x00010000; > break; > - case 0x118: /* IAUR */ > - case 0x11c: /* IALR */ > - case 0x120: /* GAUR */ > - case 0x124: /* GALR */ > + case ENET_IAUR: > + case ENET_IALR: > + case ENET_GAUR: > + case ENET_GALR: > /* TODO: implement MAC hash filtering. */ > break; > - case 0x144: /* TFWR */ > - s->tfwr =3D value & 3; > + case ENET_TFWR: > + s->regs[index] =3D value & 3; > break; > - case 0x14c: /* FRBR */ > - /* FRBR writes ignored. */ > + case ENET_FRBR: > + /* FRBR is read only */ > + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Register FRBR is read = only\n", > + TYPE_IMX_FEC, __func__); > break; > - case 0x150: /* FRSR */ > - s->frsr =3D (value & 0x3fc) | 0x400; > + case ENET_FRSR: > + s->regs[index] =3D (value & 0x000003fc) | 0x00000400; > break; > - case 0x180: /* ERDSR */ > - s->erdsr =3D value & ~3; > - s->rx_descriptor =3D s->erdsr; > + case ENET_RDSR: > + s->regs[index] =3D value & ~3; > + s->rx_descriptor =3D s->regs[index]; > break; > - case 0x184: /* ETDSR */ > - s->etdsr =3D value & ~3; > - s->tx_descriptor =3D s->etdsr; > + case ENET_TDSR: > + s->regs[index] =3D value & ~3; > + s->tx_descriptor =3D s->regs[index]; > break; > - case 0x188: /* EMRBR */ > - s->emrbr =3D value & 0x7f0; > + case ENET_MRBR: > + s->regs[index] =3D value & 0x000007f0; > break; > - case 0x300: /* MIIGSK_CFGR */ > - s->miigsk_cfgr =3D value & 0x53; > + case ENET_MIIGSK_CFGR: > + s->regs[index] =3D value & 0x00000053; > break; > - case 0x308: /* MIIGSK_ENR */ > - s->miigsk_enr =3D (value & 0x2) ? 0x6 : 0; > + case ENET_MIIGSK_ENR: > + s->regs[index] =3D (value & 0x00000002) ? 0x00000006 : 0; > break; > default: > qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset= 0x%" > - HWADDR_PRIx "\n", TYPE_IMX_FEC, __func__, addr); > + PRIx32 "\n", TYPE_IMX_FEC, __func__, index * 4); > break; > } > =20 > @@ -541,7 +589,7 @@ static int imx_fec_can_receive(NetClientState *nc) > { > IMXFECState *s =3D IMX_FEC(qemu_get_nic_opaque(nc)); > =20 > - return s->rx_enabled; > + return s->regs[ENET_RDAR] ? 1 : 0; > } > =20 > static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf= , > @@ -559,7 +607,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, = const uint8_t *buf, > =20 > FEC_PRINTF("len %d\n", (int)size); > =20 > - if (!s->rx_enabled) { > + if (!s->regs[ENET_RDAR]) { > qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n", > TYPE_IMX_FEC, __func__); > return 0; > @@ -577,7 +625,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, = const uint8_t *buf, > } > =20 > /* Frames larger than the user limit just set error flags. */ > - if (size > (s->rcr >> 16)) { > + if (size > (s->regs[ENET_RCR] >> 16)) { > flags |=3D FEC_BD_LG; > } > =20 > @@ -595,7 +643,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, = const uint8_t *buf, > TYPE_IMX_FEC, __func__); > break; > } > - buf_len =3D (size <=3D s->emrbr) ? size : s->emrbr; > + buf_len =3D (size <=3D s->regs[ENET_MRBR]) ? size : s->regs[EN= ET_MRBR]; > bd.length =3D buf_len; > size -=3D buf_len; > =20 > @@ -618,16 +666,16 @@ static ssize_t imx_fec_receive(NetClientState *nc= , const uint8_t *buf, > /* Last buffer in frame. */ > bd.flags |=3D flags | FEC_BD_L; > FEC_PRINTF("rx frame flags %04x\n", bd.flags); > - s->eir |=3D FEC_INT_RXF; > + s->regs[ENET_EIR] |=3D FEC_INT_RXF; > } else { > - s->eir |=3D FEC_INT_RXB; > + s->regs[ENET_EIR] |=3D FEC_INT_RXB; > } > imx_fec_write_bd(&bd, addr); > /* Advance to the next descriptor. */ > if ((bd.flags & FEC_BD_W) !=3D 0) { > - addr =3D s->erdsr; > + addr =3D s->regs[ENET_RDSR]; > } else { > - addr +=3D 8; > + addr +=3D sizeof(bd); > } > } > s->rx_descriptor =3D addr; > diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h > index cbf8650..709f8a0 100644 > --- a/include/hw/net/imx_fec.h > +++ b/include/hw/net/imx_fec.h > @@ -30,6 +30,33 @@ > #include "hw/sysbus.h" > #include "net/net.h" > =20 > +#define ENET_EIR 1 > +#define ENET_EIMR 2 > +#define ENET_RDAR 4 > +#define ENET_TDAR 5 > +#define ENET_ECR 9 > +#define ENET_MMFR 16 > +#define ENET_MSCR 17 > +#define ENET_MIBC 25 > +#define ENET_RCR 33 > +#define ENET_TCR 49 > +#define ENET_PALR 57 > +#define ENET_PAUR 58 > +#define ENET_OPD 59 > +#define ENET_IAUR 70 > +#define ENET_IALR 71 > +#define ENET_GAUR 72 > +#define ENET_GALR 73 > +#define ENET_TFWR 81 > +#define ENET_FRBR 83 > +#define ENET_FRSR 84 > +#define ENET_RDSR 96 > +#define ENET_TDSR 97 > +#define ENET_MRBR 98 > +#define ENET_MIIGSK_CFGR 192 > +#define ENET_MIIGSK_ENR 194 > +#define ENET_MAX 400 Is this an arbitrary value or there's a plan to add more register whose=20 index is greater than 192? > + > #define FEC_MAX_FRAME_SIZE 2032 > =20 > #define FEC_INT_HB (1 << 31) > @@ -46,8 +73,14 @@ > #define FEC_INT_RL (1 << 20) > #define FEC_INT_UN (1 << 19) > =20 > -#define FEC_EN 2 > -#define FEC_RESET 1 > +/* RDAR */ > +#define ENET_RDAR_RDAR (1 << 24) > + > +/* TDAR */ > +#define ENET_TDAR_TDAR (1 << 24) > + > +#define FEC_EN (1 << 1) > +#define FEC_RESET (1 << 0) > =20 > /* Buffer Descriptor. */ > typedef struct { > @@ -83,25 +116,9 @@ typedef struct IMXFECState { > qemu_irq irq; > MemoryRegion iomem; > =20 > - uint32_t irq_state; > - uint32_t eir; > - uint32_t eimr; > - uint32_t rx_enabled; > + uint32_t regs[ENET_MAX]; > uint32_t rx_descriptor; > uint32_t tx_descriptor; > - uint32_t ecr; > - uint32_t mmfr; > - uint32_t mscr; > - uint32_t mibc; > - uint32_t rcr; > - uint32_t tcr; > - uint32_t tfwr; > - uint32_t frsr; > - uint32_t erdsr; > - uint32_t etdsr; > - uint32_t emrbr; > - uint32_t miigsk_cfgr; > - uint32_t miigsk_enr; > =20 > uint32_t phy_status; > uint32_t phy_control;