Enhanced Three Speed Ethernet Controller (eTSEC)
cover Enhanced Three Speed Ethernet Controller (eTSEC)
I know it will be difficult to get this patch in the mainstream version, but Alex already told me that some people here may have interest in eTSEC so I thought I could just send it so everyone can have a look.
It has been tested with vxWorks and vxWorks only. I have no idea if it will work with linux. It should be backwards compatible with TSEC.
Have fun :)
Fabien Chouteau (2):
Add be16_to_cpupu function
Add Enhanced Three-Speed Ethernet Controller (eTSEC)
default-configs/ppc-softmmu.mak | 1 + hw/net/Makefile.objs | 1 + hw/net/etsec.c | 472 +++++++++++++++++++++++++++ hw/net/etsec.h | 169 ++++++++++ hw/net/etsec_miim.c | 146 +++++++++ hw/net/etsec_registers.c | 295 +++++++++++++++++ hw/net/etsec_registers.h | 302 ++++++++++++++++++ hw/net/etsec_rings.c | 673 +++++++++++++++++++++++++++++++++++++++ include/qemu/bswap.h | 5 + 9 files changed, 2064 insertions(+) create mode 100644 hw/net/etsec.c create mode 100644 hw/net/etsec.h create mode 100644 hw/net/etsec_miim.c create mode 100644 hw/net/etsec_registers.c create mode 100644 hw/net/etsec_registers.h create mode 100644 hw/net/etsec_rings.c
Signature · 1 line
1.7.9.5
PATCH 1/2 Add be16_to_cpupu function
--- include/qemu/bswap.h | 5 +++++ 1 file changed, 5 insertions(+)
include/qemu/bswap.h +5 -0
@@ -432,6 +432,11 @@ static inline uint32_t le32_to_cpupu(const uint32_t *p)return ldl_le_p (p); } +static inline uint16_t be16_to_cpupu (const uint16_t *p) +{ +return lduw_be_p (p); +} +static inline uint32_t be32_to_cpupu (const uint32_t *p) {return ldl_be_p (p);
Signature · 1 line
1.7.9.5
Re: [Qemu-devel] [PATCH 1/2] Add be16_to_cpupu function
include/qemu/bswap.h static inline uint32_t le32_to_cpupu(const uint32_t *p) · line 439
Quoted 11 lines · Fabien Chouteau
include/qemu/bswap.h +5
-0@@ -432,6 +432,11 @@ static inline uint32_t le32_to_cpupu(const uint32_t *p)return ldl_le_p (p); } +static inline uint16_t be16_to_cpupu (const uint16_t *p) +{ +return lduw_be_p (p); +} +
So these functions are preceded by the comment:
/* Legacy unaligned versions. Note that we never had a complete set. */
which suggests that we shouldn't be adding new ones. I think the correct answer is to use lduw_be_p() directly. (If so it's tempting to get rid of the legacy functions completely since the change would be pretty mechanical.)
thanks
-- PMM
Re: [Qemu-devel] [PATCH 1/2] Add be16_to_cpupu function
Quoted 16 lines · Peter Maydell
include/qemu/bswap.h static inline uint32_t le32_to_cpupu(const uint32_t *p) · line 439
Quoted 11 lines · Fabien Chouteau
include/qemu/bswap.h +5
-0@@ -432,6 +432,11 @@ static inline uint32_t le32_to_cpupu(const uint32_t *p)return ldl_le_p (p); } +static inline uint16_t be16_to_cpupu (const uint16_t *p) +{ +return lduw_be_p (p); +} +So these functions are preceded by the comment:
/* Legacy unaligned versions. Note that we never had a complete set. */
Quoted 5 lines
which suggests that we shouldn't be adding new ones. I think the correct answer is to use
lduw_be_p()directly. (If so it's tempting to get rid of the legacy functions completely since the change would be pretty mechanical.)
OK noted.
Thanks,
Signature · 1 line
Fabien Chouteau
PATCH 2/2 Add Enhanced Three-Speed Ethernet Controller (eTSEC)
In reply to Fabien ChouteauThis implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
--- default-configs/ppc-softmmu.mak | 1 + hw/net/Makefile.objs | 1 + hw/net/etsec.c | 472 +++++++++++++++++++++++++++ hw/net/etsec.h | 169 ++++++++++ hw/net/etsec_miim.c | 146 +++++++++ hw/net/etsec_registers.c | 295 +++++++++++++++++ hw/net/etsec_registers.h | 302 ++++++++++++++++++ hw/net/etsec_rings.c | 673 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 2059 insertions(+) create mode 100644 hw/net/etsec.c create mode 100644 hw/net/etsec.h create mode 100644 hw/net/etsec_miim.c create mode 100644 hw/net/etsec_registers.c create mode 100644 hw/net/etsec_registers.h create mode 100644 hw/net/etsec_rings.c
default-configs/ppc-softmmu.mak +1 -0
@@ -46,3 +46,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y +CONFIG_ETSEC=y
hw/net/Makefile.objs +1 -0
@@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o obj-$(CONFIG_PSERIES) += spapr_llan.o obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o obj-$(CONFIG_VIRTIO) += virtio-net.o obj-y += vhost_net.o
hw/net/etsec.c new file +472 -0
472 lines not on this page · raw message
hw/net/etsec.h new file +169 -0
169 lines not on this page · raw message
hw/net/etsec_miim.c new file +146 -0
146 lines not on this page · raw message
hw/net/etsec_registers.c new file +295 -0
295 lines not on this page · raw message
hw/net/etsec_registers.h new file +302 -0
302 lines not on this page · raw message
hw/net/etsec_rings.c new file +673 -0
673 lines not on this page · raw message
Signature · 1 line
1.7.9.5
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 2/2 Add Enhanced Three-Speed EthernetController (eTSEC)
Quoted 2,145 lines
-------------------------------------------------------------
发件人:Fabien Chouteau
发送日期:2013-07-11 01:11:11
收件人:qemu-devel
抄送:qemu-ppc; agraf
主题:[Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed EthernetController (eTSEC)This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Signed-off-by Fabien Chouteau <[email protected]>---
default-configs/ppc-softmmu.mak | 1 + hw/net/Makefile.objs | 1 + hw/net/etsec.c | 472 +++++++++++++++++++++++++++ hw/net/etsec.h | 169 ++++++++++ hw/net/etsec_miim.c | 146 +++++++++ hw/net/etsec_registers.c | 295 +++++++++++++++++ hw/net/etsec_registers.h | 302 ++++++++++++++++++ hw/net/etsec_rings.c | 673 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 2059 insertions(+)create mode 100644
hw/net/etsec.c
create mode 100644hw/net/etsec.h
create mode 100644hw/net/etsec_miim.c
create mode 100644hw/net/etsec_registers.c
create mode 100644hw/net/etsec_registers.h
create mode 100644hw/net/etsec_rings.cdefault-configs/ppc-softmmu.mak +0
-0@@ -46,3 +46,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP
CONFIG_MC146818RTC=ydefault-configs/ppc-softmmu.mak +1
-0+CONFIG_ETSEC=yhw/net/Makefile.objs +0
-0@@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.oobj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o obj-$(CONFIG_PSERIES) += spapr_llan.o obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o
obj-$(CONFIG_VIRTIO) += virtio-net.o
obj-y += vhost_net.ohw/net/etsec.c new file +472
-0@@ -0,0 +1,472 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "trace.h" +#include "hw/ptimer.h" +#include "hw/net/etsec.h" +#include "hw/net/etsec_registers.h" + +/* #define HEX_DUMP */ +/* #define DEBUG_REGISTER */ + +static uint64_t etsec_read (void *opaque,hwaddr addr,unsigned size) +{ +eTSEC *etsec = opaque; +uint32_t reg_index = addr /4 ; +eTSEC_Register *reg =NULL ; +uint32_t ret =0x0 ; + +assert (reg_index <REG_NUMBER ); + + reg = &etsec->regs[reg_index]; + + +switch (reg->access) { +case ACC_WO : + ret =0x00000000 ; +break ; + +case ACC_RW : +case ACC_w1c: +case ACC_RO : +default : + ret = reg->value; +break ; + } + +#ifdef DEBUG_REGISTER +printf ("Read 0x%08x @ 0x" TARGET_FMT_plx +" : %s (%s)\n" , + ret, addr, reg->name, reg->desc); +#endif + +return ret; +} + +static void write_tstat (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ +int i =0 ; + +for (i =0 ; i <8 ; i++) { +/* Check THLTi flag in TSTAT */ +if (value & (1 << (31 - i))) { +walk_tx_ring (etsec, i); + } + } + +/* Write 1 to clear */ + reg->value &= ~value; +} + +static void write_rstat (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ +int i =0 ; + +for (i =0 ; i <8 ; i++) { +/* Check QHLTi flag in RSTAT */ +if (value & (1 << (23 - i)) && !(reg->value & (1 << (23 - i)))) { +walk_rx_ring (etsec, i); + } + } + +/* Write 1 to clear */ + reg->value &= ~value; +} + +static void write_tbasex (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + reg->value = value & ~0x7 ; + +/* Copy this value in the ring's TxBD pointer */ + etsec->regs[TBPTR0 + (reg_index -TBASE0 )].value = value & ~0x7 ; +} + +static void write_rbasex (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + reg->value = value & ~0x7 ; + +/* Copy this value in the ring's RxBD pointer */ + etsec->regs[RBPTR0 + (reg_index -RBASE0 )].value = value & ~0x7 ; +} + +static void write_ievent (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ +if (value &IEVENT_TXF ) { +qemu_irq_lower (etsec->tx_irq); + } +if (value &IEVENT_RXF ) { +qemu_irq_lower (etsec->rx_irq); + } + +/* Write 1 to clear */ + reg->value &= ~value; +} + +static void write_dmactrl (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + reg->value = value; + +if (value &DMACTRL_GRS ) { + +if (etsec->rx_buffer_len !=0 ) { +/* Graceful receive stop delayed until end of frame */ + }else { +/* Graceful receive stop now */ + etsec->regs[IEVENT ].value |=IEVENT_GRSC ; +if (etsec->regs[IMASK ].value &IMASK_GRSCEN ) { +qemu_irq_raise (etsec->err_irq); + } + } + } + +if (value &DMACTRL_GTS ) { + +if (etsec->tx_buffer_len !=0 ) { +/* Graceful transmit stop delayed until end of frame */ + }else { +/* Graceful transmit stop now */ + etsec->regs[IEVENT ].value |=IEVENT_GTSC ; +if (etsec->regs[IMASK ].value &IMASK_GTSCEN ) { +qemu_irq_raise (etsec->err_irq); + } + } + } + +if (!(value &DMACTRL_WOP )) { +/* Start polling */ +ptimer_stop (etsec->ptimer); +ptimer_set_count (etsec->ptimer,1 ); +ptimer_run (etsec->ptimer,1 ); + } +} + +static void etsec_write (void *opaque, +hwaddr addr, +uint64_t value, +unsigned size) +{ +eTSEC *etsec = opaque; +uint32_t reg_index = addr /4 ; +eTSEC_Register *reg =NULL ; +uint32_t before =0x0 ; + +assert (reg_index <REG_NUMBER ); + + reg = &etsec->regs[reg_index]; + before = reg->value; + +switch (reg_index) { +case IEVENT : +write_ievent (etsec, reg, reg_index, value); +break ; + +case DMACTRL : +write_dmactrl (etsec, reg, reg_index, value); +break ; + +case TSTAT : +write_tstat (etsec, reg, reg_index, value); +break ; + +case RSTAT : +write_rstat (etsec, reg, reg_index, value); +break ; + + case TBASE0 ... TBASE7: +write_tbasex (etsec, reg, reg_index, value); +break ; + + case RBASE0 ... RBASE7: +write_rbasex (etsec, reg, reg_index, value); +break ; + + case MIIMCFG ... MIIMIND: +write_miim (etsec, reg, reg_index, value); +break ; + +default : +/* Default handling */ +switch (reg->access) { + +case ACC_RW : +case ACC_WO : + reg->value = value; +break ; + +case ACC_w1c: + reg->value &= ~value; +break ; + +case ACC_RO : +default : +/* Read Only or Unknown register */ +break ; + } + } + +#ifdef DEBUG_REGISTER +printf ("Write 0x%08x @ 0x" TARGET_FMT_plx" val:0x%08x->0x%08x : %s (%s)\n" , + (unsigned int )value, addr, before, reg->value, reg->name, reg->desc); +#else + (void )before;/* Unreferenced */ +#endif + +} + +static const MemoryRegionOps etsec_ops = { + .read = etsec_read, + .write = etsec_write, + .endianness =DEVICE_NATIVE_ENDIAN , + .impl = { + .min_access_size =4 , + .max_access_size =4 , + }, +}; + +static void etsec_timer_hit (void *opaque) +{ +eTSEC *etsec = opaque; + +ptimer_stop (etsec->ptimer); + +if (!(etsec->regs[DMACTRL ].value &DMACTRL_WOP )) { + +if (!(etsec->regs[DMACTRL ].value &DMACTRL_GTS )) { +walk_tx_ring (etsec,0 ); + } +ptimer_set_count (etsec->ptimer,1 ); +ptimer_run (etsec->ptimer,1 ); + } +} + +static void etsec_reset (DeviceState *d) +{ +eTSEC *etsec =container_of (d, eTSEC, busdev.qdev); +int i =0 ; +int reg_index =0 ; + +/* Default value for all registers */ +for (i =0 ; i <REG_NUMBER ; i++) { + etsec->regs[i].name ="Reserved" ; + etsec->regs[i].desc ="" ; + etsec->regs[i].access =ACC_UNKNOWN ; + etsec->regs[i].value =0x00000000 ; + } + +/* Set-up known registers */ +for (i =0 ; eTSEC_registers_def[i].name !=NULL ; i++) { + + reg_index = eTSEC_registers_def[i].offset /4 ; + + etsec->regs[reg_index].name = eTSEC_registers_def[i].name; + etsec->regs[reg_index].desc = eTSEC_registers_def[i].desc; + etsec->regs[reg_index].access = eTSEC_registers_def[i].access; + etsec->regs[reg_index].value = eTSEC_registers_def[i].reset; + } + + etsec->tx_buffer =NULL ; + etsec->tx_buffer_len =0 ; + etsec->rx_buffer =NULL ; + etsec->rx_buffer_len =0 ; + + etsec->phy_status = +MII_SR_EXTENDED_CAPS |MII_SR_LINK_STATUS |MII_SR_AUTONEG_CAPS | +MII_SR_AUTONEG_COMPLETE |MII_SR_PREAMBLE_SUPPRESS | +MII_SR_EXTENDED_STATUS |MII_SR_100T2_HD_CAPS |MII_SR_100T2_FD_CAPS | +MII_SR_10T_HD_CAPS |MII_SR_10T_FD_CAPS |MII_SR_100X_HD_CAPS | +MII_SR_100X_FD_CAPS |MII_SR_100T4_CAPS ; +} + +static void etsec_cleanup (NetClientState *nc) +{ +/* printf("eTSEC cleanup\n"); */ +} + +static int etsec_can_receive (NetClientState *nc) +{ +/* Yes we always can\ */ +return 1 ; +} + +#ifdef HEX_DUMP +static void hex_dump (FILE *f,const uint8_t *buf,int size) +{ +int len, i, j, c; + +for (i =0 ; i < size; i +=16 ) { + len = size - i; +if (len >16 ) { + len =16 ; + } +fprintf (f,"%08x " , i); +for (j =0 ; j <16 ; j++) { +if (j < len) { +fprintf (f," %02x" , buf[i + j]); + }else { +fprintf (f," " ); + } + } +fprintf (f," " ); +for (j =0 ; j < len; j++) { + c = buf[i + j]; +if (c <' ' || c >'~' ) { + c ='.' ; + } +fprintf (f,"%c" , c); + } +fprintf (f,"\n" ); + } +} +#endif + +static ssize_t etsec_receive (NetClientState *nc, +const uint8_t *buf, +size_t size) +{ +eTSEC *etsec =qemu_get_nic_opaque (nc); + +#if defined(HEX_DUMP ) +fprintf (stderr,"%s receive size:%d\n" , etsec->nic->nc.name, size); +hex_dump (stderr, buf, size); +#endif +rx_ring_write (etsec, buf, size); +return size; +} + + +static void etsec_set_link_status (NetClientState *nc) +{ +eTSEC *etsec =qemu_get_nic_opaque (nc); + +miim_link_status (etsec, nc); +} + +static NetClientInfo net_etsec_info = { + .type =NET_CLIENT_OPTIONS_KIND_NIC , + .size =sizeof (NICState), + .can_receive = etsec_can_receive, + .receive = etsec_receive, + .cleanup = etsec_cleanup, + .link_status_changed = etsec_set_link_status, +}; + +static int etsec_init (SysBusDevice *dev) +{ +eTSEC *etsec =FROM_SYSBUS (typeof (*etsec), dev); + +memory_region_init_io (&etsec->io_area,OBJECT (etsec), &etsec_ops, etsec, +"eTSEC" ,0x1000 ); + +sysbus_init_mmio (dev, &etsec->io_area); + +sysbus_init_irq (dev, &etsec->tx_irq); +sysbus_init_irq (dev, &etsec->rx_irq); +sysbus_init_irq (dev, &etsec->err_irq); + + etsec->nic =qemu_new_nic (&net_etsec_info, &etsec->conf, +"eTSEC" , etsec->busdev.qdev.id, etsec); +qemu_format_nic_info_str (qemu_get_queue (etsec->nic), etsec->conf.macaddr.a); + + + etsec->bh =qemu_bh_new (etsec_timer_hit, etsec); + etsec->ptimer =ptimer_init (etsec->bh); +ptimer_set_freq (etsec->ptimer,100 ); + +return 0 ; +} + +static Property etsec_properties[] = { +DEFINE_NIC_PROPERTIES (eTSEC, conf), +DEFINE_PROP_END_OF_LIST (), +}; + +static void etsec_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = etsec_init; + dc->reset = etsec_reset; + dc->props = etsec_properties; +} + +static TypeInfo etsec_info = { + .name ="eTSEC" , + .parent =TYPE_SYS_BUS_DEVICE , + .instance_size =sizeof (eTSEC), + .class_init = etsec_class_init, +}; + +static void etsec_register_types (void ) +{ +type_register_static (&etsec_info); +} + +type_init (etsec_register_types) + +DeviceState *etsec_create(hwaddr base, +MemoryRegion * mr, +NICInfo * nd, +qemu_irq tx_irq, +qemu_irq rx_irq, +qemu_irq err_irq) +{ +DeviceState *dev; + + dev =qdev_create (NULL ,"eTSEC" ); +qdev_set_nic_properties (dev, nd); + +if (qdev_init (dev)) { +return NULL ; + } + +sysbus_connect_irq (SYS_BUS_DEVICE (dev),0 , tx_irq); +sysbus_connect_irq (SYS_BUS_DEVICE (dev),1 , rx_irq); +sysbus_connect_irq (SYS_BUS_DEVICE (dev),2 , err_irq); + +memory_region_add_subregion (mr, base, +SYS_BUS_DEVICE (dev)->mmio[0 ].memory); + +return dev; +}hw/net/etsec.h new file +169
-0@@ -0,0 +1,169 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef _ETSEC_H_ +#define _ETSEC_H_ + +#include "hw/qdev.h" +#include "hw/sysbus.h" +#include "net/net.h" +#include "hw/ptimer.h" + +/* Buffer Descriptors */ + +typedef struct eTSEC_rxtx_bd { +uint16_t flags; +uint16_t length; +uint32_t bufptr; +}eTSEC_rxtx_bd ; + +#define BD_WRAP (1 << 13) +#define BD_INTERRUPT (1 << 12) +#define BD_LAST (1 << 11) + +#define BD_TX_READY (1 << 15) +#define BD_TX_PADCRC (1 << 14) +#define BD_TX_TC (1 << 10) +#define BD_TX_PREDEF (1 << 9) +#define BD_TX_HFELC (1 << 7) +#define BD_TX_CFRL (1 << 6) +#define BD_TX_RC_MASK 0xF +#define BD_TX_RC_OFFSET 0x2 +#define BD_TX_TOEUN (1 << 1) +#define BD_TX_TR (1 << 0) + +#define BD_RX_EMPTY (1 << 15) +#define BD_RX_RO1 (1 << 14) +#define BD_RX_FIRST (1 << 10) +#define BD_RX_MISS (1 << 8) +#define BD_RX_BROADCAST (1 << 7) +#define BD_RX_MULTICAST (1 << 6) +#define BD_RX_LG (1 << 5) +#define BD_RX_NO (1 << 4) +#define BD_RX_SH (1 << 3) +#define BD_RX_CR (1 << 2) +#define BD_RX_OV (1 << 1) +#define BD_RX_TR (1 << 0) + +/* Tx FCB flags */ +#define FCB_TX_VLN (1 << 7) +#define FCB_TX_IP (1 << 6) +#define FCB_TX_IP6 (1 << 5) +#define FCB_TX_TUP (1 << 4) +#define FCB_TX_UDP (1 << 3) +#define FCB_TX_CIP (1 << 2) +#define FCB_TX_CTU (1 << 1) +#define FCB_TX_NPH (1 << 0) + +/* PHY Status Register */ +#define MII_SR_EXTENDED_CAPS 0x0001/* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002/* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004/* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008/* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010/* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020/* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040/* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100/* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200/* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400/* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800/* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000/* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000/* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000/* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000/* 100T4 Capable */ + +/* eTSEC */ + +#define REG_NUMBER 1024 + +typedef struct eTSEC_Register { +const char *name; +const char *desc; +uint32_t access; +uint32_t value; +}eTSEC_Register ; + +typedef struct eTSEC { +SysBusDevice busdev; + +MemoryRegion io_area; + +eTSEC_Register regs[REG_NUMBER ]; + +NICState *nic; +NICConf conf; + +/* Tx */ + +uint8_t *tx_buffer; +uint32_t tx_buffer_len; +eTSEC_rxtx_bd first_bd; + +/* Rx */ + +uint8_t *rx_buffer; +uint32_t rx_buffer_len; +uint32_t rx_remaining_data; +uint8_t rx_first_in_frame; +uint8_t rx_fcb_size; +eTSEC_rxtx_bd rx_first_bd; +uint8_t rx_fcb[10 ]; +uint32_t rx_padding; + +/* IRQs */ +qemu_irq tx_irq; +qemu_irq rx_irq; +qemu_irq err_irq; + + +uint16_t phy_status; +uint16_t phy_control; + +/* Polling */ +QEMUBH *bh; +struct ptimer_state *ptimer; + +}eTSEC ; + +#define eTSEC_TRANSMIT 1 +#define eTSEC_RECEIVE 2 + +DeviceState *etsec_create (hwaddr base, +MemoryRegion *mr, +NICInfo *nd, +qemu_irq tx_irq, +qemu_irq rx_irq, +qemu_irq err_irq); + +void walk_tx_ring (eTSEC *etsec,int ring_nbr); +void walk_rx_ring (eTSEC *etsec,int ring_nbr); +void rx_ring_write (eTSEC *etsec,const uint8_t *buf,size_t size); + +void write_miim (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value); + +void miim_link_status (eTSEC *etsec,NetClientState *nc); + +#endif /* ! _ETSEC_H_ */ hw/net/etsec_miim.c new file +146
-0@@ -0,0 +1,146 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "etsec.h" +#include "etsec_registers.h" + +/* #define DEBUG_MIIM */ + +#define MIIM_CONTROL 0 +#define MIIM_STATUS 1 +#define MIIM_PHY_ID_1 2 +#define MIIM_PHY_ID_2 3 +#define MIIM_T2_STATUS 10 +#define MIIM_EXT_STATUS 15 + +static void miim_read_cycle (eTSEC *etsec) +{ +uint8_t phy; +uint8_t addr; +uint16_t value; + + phy = (etsec->regs[MIIMADD ].value >>8 ) &0x1F ; + (void )phy;/* Unreferenced */ + addr = etsec->regs[MIIMADD ].value &0x1F ; + +switch (addr) { +case MIIM_CONTROL : + value = etsec->phy_control; +break ; +case MIIM_STATUS : + value = etsec->phy_status; +break ; +case MIIM_T2_STATUS : + value =0x1800 ;/* Local and remote receivers OK */ +break ; +default : + value =0x0 ; +break ; + }; + +#ifdef DEBUG_MIIM +printf ("%s phy:%d addr:0x%x value:0x%x\n" , __func__, phy, addr, value); +#endif + + etsec->regs[MIIMSTAT ].value = value; +} + +static void miim_write_cycle (eTSEC *etsec) +{ +uint8_t phy; +uint8_t addr; +uint16_t value; + + phy = (etsec->regs[MIIMADD ].value >>8 ) &0x1F ; + (void )phy;/* Unreferenced */ + addr = etsec->regs[MIIMADD ].value &0x1F ; + value = etsec->regs[MIIMCON ].value &0xffff ; + +#ifdef DEBUG_MIIM +printf ("%s phy:%d addr:0x%x value:0x%x\n" , __func__, phy, addr, value); +#endif + +switch (addr) { +case MIIM_CONTROL : + etsec->phy_control = value & ~(0x8100 ); +break ; +default : +break ; + }; +} + +void write_miim (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + +switch (reg_index) { + +case MIIMCOM : +/* Read and scan cycle */ + +if ((!(reg->value &MIIMCOM_READ )) && (value &MIIMCOM_READ )) { +/* Read */ +miim_read_cycle (etsec); + } + reg->value = value; +break ; + +case MIIMCON : + reg->value = value &0xffff ; +miim_write_cycle (etsec); +break ; + +default : +/* Default handling */ +switch (reg->access) { + +case ACC_RW : +case ACC_WO : + reg->value = value; +break ; + +case ACC_w1c: + reg->value &= ~value; +break ; + +case ACC_RO : +default : +/* Read Only or Unknown register */ +break ; + } + } + +} + +void miim_link_status (eTSEC *etsec,NetClientState *nc) +{ +/* Set link status */ +if (nc->link_down) { + etsec->phy_status &= ~MII_SR_LINK_STATUS ; + }else { + etsec->phy_status |=MII_SR_LINK_STATUS ; + } +}hw/net/etsec_registers.c new file +295
-0@@ -0,0 +1,295 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#include "etsec_registers.h" + +const eTSEC_Register_Definition eTSEC_registers_def[] = { +{0x000 ,"TSEC_ID" ,"Controller ID register" ,ACC_RO ,0x01240000 }, +{0x004 ,"TSEC_ID2" ,"Controller ID register 2" ,ACC_RO ,0x003000F0 }, +{0x010 ,"IEVENT" ,"Interrupt event register" , ACC_w1c,0x00000000 }, +{0x014 ,"IMASK" ,"Interrupt mask register" ,ACC_RW ,0x00000000 }, +{0x018 ,"EDIS" ,"Error disabled register" ,ACC_RW ,0x00000000 }, +{0x020 ,"ECNTRL" ,"Ethernet control register" ,ACC_RW ,0x00000040 }, +{0x028 ,"PTV" ,"Pause time value register" ,ACC_RW ,0x00000000 }, +{0x02C ,"DMACTRL" ,"DMA control register" ,ACC_RW ,0x00000000 }, +{0x030 ,"TBIPA" ,"TBI PHY address register" ,ACC_RW ,0x00000000 }, + +/* eTSEC FIFO Control and Status Registers */ + +{0x058 ,"FIFO_RX_ALARM" ,"FIFO receive alarm start threshold register" ,ACC_RW ,0x00000040 }, +{0x05C ,"FIFO_RX_ALARM_SHUTOFF" ,"FIFO receive alarm shut-off threshold register" ,ACC_RW ,0x00000080 }, +{0x08C ,"FIFO_TX_THR" ,"FIFO transmit threshold register" ,ACC_RW ,0x00000080 }, +{0x098 ,"FIFO_TX_STARVE" ,"FIFO transmit starve register" ,ACC_RW ,0x00000040 }, +{0x09C ,"FIFO_TX_STARVE_SHUTOFF" ,"FIFO transmit starve shut-off register" ,ACC_RW ,0x00000080 }, + +/* eTSEC Transmit Control and Status Registers */ + +{0x100 ,"TCTRL" ,"Transmit control register" ,ACC_RW ,0x00000000 }, +{0x104 ,"TSTAT" ,"Transmit status register" , ACC_w1c,0x00000000 }, +{0x108 ,"DFVLAN" ,"Default VLAN control word" ,ACC_RW ,0x81000000 }, +{0x110 ,"TXIC" ,"Transmit interrupt coalescing register" ,ACC_RW ,0x00000000 }, +{0x114 ,"TQUEUE" ,"Transmit queue control register" ,ACC_RW ,0x00008000 }, +{0x140 ,"TR03WT" ,"TxBD Rings 0-3 round-robin weightings" ,ACC_RW ,0x00000000 }, +{0x144 ,"TR47WT" ,"TxBD Rings 4-7 round-robin weightings" ,ACC_RW ,0x00000000 }, +{0x180 ,"TBDBPH" ,"Tx data buffer pointer high bits" ,ACC_RW ,0x00000000 }, +{0x184 ,"TBPTR0" ,"TxBD pointer for ring 0" ,ACC_RW ,0x00000000 }, +{0x18C ,"TBPTR1" ,"TxBD pointer for ring 1" ,ACC_RW ,0x00000000 }, +{0x194 ,"TBPTR2" ,"TxBD pointer for ring 2" ,ACC_RW ,0x00000000 }, +{0x19C ,"TBPTR3" ,"TxBD pointer for ring 3" ,ACC_RW ,0x00000000 }, +{0x1A4 ,"TBPTR4" ,"TxBD pointer for ring 4" ,ACC_RW ,0x00000000 }, +{0x1AC ,"TBPTR5" ,"TxBD pointer for ring 5" ,ACC_RW ,0x00000000 }, +{0x1B4 ,"TBPTR6" ,"TxBD pointer for ring 6" ,ACC_RW ,0x00000000 }, +{0x1BC ,"TBPTR7" ,"TxBD pointer for ring 7" ,ACC_RW ,0x00000000 }, +{0x200 ,"TBASEH" ,"TxBD base address high bits" ,ACC_RW ,0x00000000 }, +{0x204 ,"TBASE0" ,"TxBD base address of ring 0" ,ACC_RW ,0x00000000 }, +{0x20C ,"TBASE1" ,"TxBD base address of ring 1" ,ACC_RW ,0x00000000 }, +{0x214 ,"TBASE2" ,"TxBD base address of ring 2" ,ACC_RW ,0x00000000 }, +{0x21C ,"TBASE3" ,"TxBD base address of ring 3" ,ACC_RW ,0x00000000 }, +{0x224 ,"TBASE4" ,"TxBD base address of ring 4" ,ACC_RW ,0x00000000 }, +{0x22C ,"TBASE5" ,"TxBD base address of ring 5" ,ACC_RW ,0x00000000 }, +{0x234 ,"TBASE6" ,"TxBD base address of ring 6" ,ACC_RW ,0x00000000 }, +{0x23C ,"TBASE7" ,"TxBD base address of ring 7" ,ACC_RW ,0x00000000 }, +{0x280 ,"TMR_TXTS1_ID" ,"Tx time stamp identification tag (set 1)" ,ACC_RO ,0x00000000 }, +{0x284 ,"TMR_TXTS2_ID" ,"Tx time stamp identification tag (set 2)" ,ACC_RO ,0x00000000 }, +{0x2C0 ,"TMR_TXTS1_H" ,"Tx time stamp high (set 1)" ,ACC_RO ,0x00000000 }, +{0x2C4 ,"TMR_TXTS1_L" ,"Tx time stamp high (set 1)" ,ACC_RO ,0x00000000 }, +{0x2C8 ,"TMR_TXTS2_H" ,"Tx time stamp high (set 2)" ,ACC_RO ,0x00000000 }, +{0x2CC ,"TMR_TXTS2_L" ,"Tx time stamp high (set 2)" ,ACC_RO ,0x00000000 }, + +/* eTSEC Receive Control and Status Registers */ + +{0x300 ,"RCTRL" ,"Receive control register" ,ACC_RW ,0x00000000 }, +{0x304 ,"RSTAT" ,"Receive status register" , ACC_w1c,0x00000000 }, +{0x310 ,"RXIC" ,"Receive interrupt coalescing register" ,ACC_RW ,0x00000000 }, +{0x314 ,"RQUEUE" ,"Receive queue control register." ,ACC_RW ,0x00800080 }, +{0x330 ,"RBIFX" ,"Receive bit field extract control register" ,ACC_RW ,0x00000000 }, +{0x334 ,"RQFAR" ,"Receive queue filing table address register" ,ACC_RW ,0x00000000 }, +{0x338 ,"RQFCR" ,"Receive queue filing table control register" ,ACC_RW ,0x00000000 }, +{0x33C ,"RQFPR" ,"Receive queue filing table property register" ,ACC_RW ,0x00000000 }, +{0x340 ,"MRBLR" ,"Maximum receive buffer length register" ,ACC_RW ,0x00000000 }, +{0x380 ,"RBDBPH" ,"Rx data buffer pointer high bits" ,ACC_RW ,0x00000000 }, +{0x384 ,"RBPTR0" ,"RxBD pointer for ring 0" ,ACC_RW ,0x00000000 }, +{0x38C ,"RBPTR1" ,"RxBD pointer for ring 1" ,ACC_RW ,0x00000000 }, +{0x394 ,"RBPTR2" ,"RxBD pointer for ring 2" ,ACC_RW ,0x00000000 }, +{0x39C ,"RBPTR3" ,"RxBD pointer for ring 3" ,ACC_RW ,0x00000000 }, +{0x3A4 ,"RBPTR4" ,"RxBD pointer for ring 4" ,ACC_RW ,0x00000000 }, +{0x3AC ,"RBPTR5" ,"RxBD pointer for ring 5" ,ACC_RW ,0x00000000 }, +{0x3B4 ,"RBPTR6" ,"RxBD pointer for ring 6" ,ACC_RW ,0x00000000 }, +{0x3BC ,"RBPTR7" ,"RxBD pointer for ring 7" ,ACC_RW ,0x00000000 }, +{0x400 ,"RBASEH" ,"RxBD base address high bits" ,ACC_RW ,0x00000000 }, +{0x404 ,"RBASE0" ,"RxBD base address of ring 0" ,ACC_RW ,0x00000000 }, +{0x40C ,"RBASE1" ,"RxBD base address of ring 1" ,ACC_RW ,0x00000000 }, +{0x414 ,"RBASE2" ,"RxBD base address of ring 2" ,ACC_RW ,0x00000000 }, +{0x41C ,"RBASE3" ,"RxBD base address of ring 3" ,ACC_RW ,0x00000000 }, +{0x424 ,"RBASE4" ,"RxBD base address of ring 4" ,ACC_RW ,0x00000000 }, +{0x42C ,"RBASE5" ,"RxBD base address of ring 5" ,ACC_RW ,0x00000000 }, +{0x434 ,"RBASE6" ,"RxBD base address of ring 6" ,ACC_RW ,0x00000000 }, +{0x43C ,"RBASE7" ,"RxBD base address of ring 7" ,ACC_RW ,0x00000000 }, +{0x4C0 ,"TMR_RXTS_H" ,"Rx timer time stamp register high" ,ACC_RW ,0x00000000 }, +{0x4C4 ,"TMR_RXTS_L" ,"Rx timer time stamp register low" ,ACC_RW ,0x00000000 }, + +/* eTSEC MAC Registers */ + +{0x500 ,"MACCFG1" ,"MAC configuration register 1" ,ACC_RW ,0x00000000 }, +{0x504 ,"MACCFG2" ,"MAC configuration register 2" ,ACC_RW ,0x00007000 }, +{0x508 ,"IPGIFG" ,"Inter-packet/inter-frame gap register" ,ACC_RW ,0x40605060 }, +{0x50C ,"HAFDUP" ,"Half-duplex control" ,ACC_RW ,0x00A1F037 }, +{0x510 ,"MAXFRM" ,"Maximum frame length" ,ACC_RW ,0x00000600 }, +{0x520 ,"MIIMCFG" ,"MII management configuration" ,ACC_RW ,0x00000007 }, +{0x524 ,"MIIMCOM" ,"MII management command" ,ACC_RW ,0x00000000 }, +{0x528 ,"MIIMADD" ,"MII management address" ,ACC_RW ,0x00000000 }, +{0x52C ,"MIIMCON" ,"MII management control" ,ACC_WO ,0x00000000 }, +{0x530 ,"MIIMSTAT" ,"MII management status" ,ACC_RO ,0x00000000 }, +{0x534 ,"MIIMIND" ,"MII management indicator" ,ACC_RO ,0x00000000 }, +{0x53C ,"IFSTAT" ,"Interface status" ,ACC_RO ,0x00000000 }, +{0x540 ,"MACSTNADDR1" ,"MAC station address register 1" ,ACC_RW ,0x00000000 }, +{0x544 ,"MACSTNADDR2" ,"MAC station address register 2" ,ACC_RW ,0x00000000 }, +{0x548 ,"MAC01ADDR1" ,"MAC exact match address 1, part 1" ,ACC_RW ,0x00000000 }, +{0x54C ,"MAC01ADDR2" ,"MAC exact match address 1, part 2" ,ACC_RW ,0x00000000 }, +{0x550 ,"MAC02ADDR1" ,"MAC exact match address 2, part 1" ,ACC_RW ,0x00000000 }, +{0x554 ,"MAC02ADDR2" ,"MAC exact match address 2, part 2" ,ACC_RW ,0x00000000 }, +{0x558 ,"MAC03ADDR1" ,"MAC exact match address 3, part 1" ,ACC_RW ,0x00000000 }, +{0x55C ,"MAC03ADDR2" ,"MAC exact match address 3, part 2" ,ACC_RW ,0x00000000 }, +{0x560 ,"MAC04ADDR1" ,"MAC exact match address 4, part 1" ,ACC_RW ,0x00000000 }, +{0x564 ,"MAC04ADDR2" ,"MAC exact match address 4, part 2" ,ACC_RW ,0x00000000 }, +{0x568 ,"MAC05ADDR1" ,"MAC exact match address 5, part 1" ,ACC_RW ,0x00000000 }, +{0x56C ,"MAC05ADDR2" ,"MAC exact match address 5, part 2" ,ACC_RW ,0x00000000 }, +{0x570 ,"MAC06ADDR1" ,"MAC exact match address 6, part 1" ,ACC_RW ,0x00000000 }, +{0x574 ,"MAC06ADDR2" ,"MAC exact match address 6, part 2" ,ACC_RW ,0x00000000 }, +{0x578 ,"MAC07ADDR1" ,"MAC exact match address 7, part 1" ,ACC_RW ,0x00000000 }, +{0x57C ,"MAC07ADDR2" ,"MAC exact match address 7, part 2" ,ACC_RW ,0x00000000 }, +{0x580 ,"MAC08ADDR1" ,"MAC exact match address 8, part 1" ,ACC_RW ,0x00000000 }, +{0x584 ,"MAC08ADDR2" ,"MAC exact match address 8, part 2" ,ACC_RW ,0x00000000 }, +{0x588 ,"MAC09ADDR1" ,"MAC exact match address 9, part 1" ,ACC_RW ,0x00000000 }, +{0x58C ,"MAC09ADDR2" ,"MAC exact match address 9, part 2" ,ACC_RW ,0x00000000 }, +{0x590 ,"MAC10ADDR1" ,"MAC exact match address 10, part 1" ,ACC_RW ,0x00000000 }, +{0x594 ,"MAC10ADDR2" ,"MAC exact match address 10, part 2" ,ACC_RW ,0x00000000 }, +{0x598 ,"MAC11ADDR1" ,"MAC exact match address 11, part 1" ,ACC_RW ,0x00000000 }, +{0x59C ,"MAC11ADDR2" ,"MAC exact match address 11, part 2" ,ACC_RW ,0x00000000 }, +{0x5A0 ,"MAC12ADDR1" ,"MAC exact match address 12, part 1" ,ACC_RW ,0x00000000 }, +{0x5A4 ,"MAC12ADDR2" ,"MAC exact match address 12, part 2" ,ACC_RW ,0x00000000 }, +{0x5A8 ,"MAC13ADDR1" ,"MAC exact match address 13, part 1" ,ACC_RW ,0x00000000 }, +{0x5AC ,"MAC13ADDR2" ,"MAC exact match address 13, part 2" ,ACC_RW ,0x00000000 }, +{0x5B0 ,"MAC14ADDR1" ,"MAC exact match address 14, part 1" ,ACC_RW ,0x00000000 }, +{0x5B4 ,"MAC14ADDR2" ,"MAC exact match address 14, part 2" ,ACC_RW ,0x00000000 }, +{0x5B8 ,"MAC15ADDR1" ,"MAC exact match address 15, part 1" ,ACC_RW ,0x00000000 }, +{0x5BC ,"MAC15ADDR2" ,"MAC exact match address 15, part 2" ,ACC_RW ,0x00000000 }, + +/* eTSEC, "Transmit", "and", Receive, Counters */ + +{0x680 ,"TR64" ,"Transmit and receive 64-byte frame counter " ,ACC_RW ,0x00000000 }, +{0x684 ,"TR127" ,"Transmit and receive 65- to 127-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x688 ,"TR255" ,"Transmit and receive 128- to 255-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x68C ,"TR511" ,"Transmit and receive 256- to 511-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x690 ,"TR1K" ,"Transmit and receive 512- to 1023-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x694 ,"TRMAX" ,"Transmit and receive 1024- to 1518-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x698 ,"TRMGV" ,"Transmit and receive 1519- to 1522-byte good VLAN frame count" ,ACC_RW ,0x00000000 }, + +/* eTSEC Receive Counters */ + +{0x69C ,"RBYT" ,"Receive byte counter" ,ACC_RW ,0x00000000 }, +{0x6A0 ,"RPKT" ,"Receive packet counter" ,ACC_RW ,0x00000000 }, +{0x6A4 ,"RFCS" ,"Receive FCS error counter" ,ACC_RW ,0x00000000 }, +{0x6A8 ,"RMCA" ,"Receive multicast packet counter" ,ACC_RW ,0x00000000 }, +{0x6AC ,"RBCA" ,"Receive broadcast packet counter" ,ACC_RW ,0x00000000 }, +{0x6B0 ,"RXCF" ,"Receive control frame packet counter " ,ACC_RW ,0x00000000 }, +{0x6B4 ,"RXPF" ,"Receive PAUSE frame packet counter" ,ACC_RW ,0x00000000 }, +{0x6B8 ,"RXUO" ,"Receive unknown OP code counter " ,ACC_RW ,0x00000000 }, +{0x6BC ,"RALN" ,"Receive alignment error counter " ,ACC_RW ,0x00000000 }, +{0x6C0 ,"RFLR" ,"Receive frame length error counter " ,ACC_RW ,0x00000000 }, +{0x6C4 ,"RCDE" ,"Receive code error counter " ,ACC_RW ,0x00000000 }, +{0x6C8 ,"RCSE" ,"Receive carrier sense error counter" ,ACC_RW ,0x00000000 }, +{0x6CC ,"RUND" ,"Receive undersize packet counter" ,ACC_RW ,0x00000000 }, +{0x6D0 ,"ROVR" ,"Receive oversize packet counter " ,ACC_RW ,0x00000000 }, +{0x6D4 ,"RFRG" ,"Receive fragments counter" ,ACC_RW ,0x00000000 }, +{0x6D8 ,"RJBR" ,"Receive jabber counter " ,ACC_RW ,0x00000000 }, +{0x6DC ,"RDRP" ,"Receive drop counter" ,ACC_RW ,0x00000000 }, + +/* eTSEC Transmit Counters */ + +{0x6E0 ,"TBYT" ,"Transmit byte counter" ,ACC_RW ,0x00000000 }, +{0x6E4 ,"TPKT" ,"Transmit packet counter" ,ACC_RW ,0x00000000 }, +{0x6E8 ,"TMCA" ,"Transmit multicast packet counter " ,ACC_RW ,0x00000000 }, +{0x6EC ,"TBCA" ,"Transmit broadcast packet counter " ,ACC_RW ,0x00000000 }, +{0x6F0 ,"TXPF" ,"Transmit PAUSE control frame counter " ,ACC_RW ,0x00000000 }, +{0x6F4 ,"TDFR" ,"Transmit deferral packet counter " ,ACC_RW ,0x00000000 }, +{0x6F8 ,"TEDF" ,"Transmit excessive deferral packet counter " ,ACC_RW ,0x00000000 }, +{0x6FC ,"TSCL" ,"Transmit single collision packet counter" ,ACC_RW ,0x00000000 }, +{0x700 ,"TMCL" ,"Transmit multiple collision packet counter" ,ACC_RW ,0x00000000 }, +{0x704 ,"TLCL" ,"Transmit late collision packet counter" ,ACC_RW ,0x00000000 }, +{0x708 ,"TXCL" ,"Transmit excessive collision packet counter" ,ACC_RW ,0x00000000 }, +{0x70C ,"TNCL" ,"Transmit total collision counter " ,ACC_RW ,0x00000000 }, +{0x714 ,"TDRP" ,"Transmit drop frame counter" ,ACC_RW ,0x00000000 }, +{0x718 ,"TJBR" ,"Transmit jabber frame counter " ,ACC_RW ,0x00000000 }, +{0x71C ,"TFCS" ,"Transmit FCS error counter" ,ACC_RW ,0x00000000 }, +{0x720 ,"TXCF" ,"Transmit control frame counter " ,ACC_RW ,0x00000000 }, +{0x724 ,"TOVR" ,"Transmit oversize frame counter" ,ACC_RW ,0x00000000 }, +{0x728 ,"TUND" ,"Transmit undersize frame counter " ,ACC_RW ,0x00000000 }, +{0x72C ,"TFRG" ,"Transmit fragments frame counter " ,ACC_RW ,0x00000000 }, + +/* eTSEC Counter Control and TOE Statistics Registers */ + +{0x730 ,"CAR1" ,"Carry register one register" , ACC_w1c,0x00000000 }, +{0x734 ,"CAR2" ,"Carry register two register " , ACC_w1c,0x00000000 }, +{0x738 ,"CAM1" ,"Carry register one mask register " ,ACC_RW ,0xFE03FFFF }, +{0x73C ,"CAM2" ,"Carry register two mask register " ,ACC_RW ,0x000FFFFD }, +{0x740 ,"RREJ" ,"Receive filer rejected packet counter" ,ACC_RW ,0x00000000 }, + +/* Hash Function Registers */ + +{0x800 ,"IGADDR0" ,"Individual/group address register 0" ,ACC_RW ,0x00000000 }, +{0x804 ,"IGADDR1" ,"Individual/group address register 1" ,ACC_RW ,0x00000000 }, +{0x808 ,"IGADDR2" ,"Individual/group address register 2" ,ACC_RW ,0x00000000 }, +{0x80C ,"IGADDR3" ,"Individual/group address register 3" ,ACC_RW ,0x00000000 }, +{0x810 ,"IGADDR4" ,"Individual/group address register 4" ,ACC_RW ,0x00000000 }, +{0x814 ,"IGADDR5" ,"Individual/group address register 5" ,ACC_RW ,0x00000000 }, +{0x818 ,"IGADDR6" ,"Individual/group address register 6" ,ACC_RW ,0x00000000 }, +{0x81C ,"IGADDR7" ,"Individual/group address register 7" ,ACC_RW ,0x00000000 }, +{0x880 ,"GADDR0" ,"Group address register 0" ,ACC_RW ,0x00000000 }, +{0x884 ,"GADDR1" ,"Group address register 1" ,ACC_RW ,0x00000000 }, +{0x888 ,"GADDR2" ,"Group address register 2" ,ACC_RW ,0x00000000 }, +{0x88C ,"GADDR3" ,"Group address register 3" ,ACC_RW ,0x00000000 }, +{0x890 ,"GADDR4" ,"Group address register 4" ,ACC_RW ,0x00000000 }, +{0x894 ,"GADDR5" ,"Group address register 5" ,ACC_RW ,0x00000000 }, +{0x898 ,"GADDR6" ,"Group address register 6" ,ACC_RW ,0x00000000 }, +{0x89C ,"GADDR7" ,"Group address register 7" ,ACC_RW ,0x00000000 }, + +/* eTSEC DMA Attribute Registers */ + +{0xBF8 ,"ATTR" ,"Attribute register" ,ACC_RW ,0x00000000 }, +{0xBFC ,"ATTRELI" ,"Attribute extract length and extract index register" ,ACC_RW ,0x00000000 }, + + +/* eTSEC Lossless Flow Control Registers */ + +{0xC00 ,"RQPRM0" ,"Receive Queue Parameters register 0 " ,ACC_RW ,0x00000000 }, +{0xC04 ,"RQPRM1" ,"Receive Queue Parameters register 1 " ,ACC_RW ,0x00000000 }, +{0xC08 ,"RQPRM2" ,"Receive Queue Parameters register 2 " ,ACC_RW ,0x00000000 }, +{0xC0C ,"RQPRM3" ,"Receive Queue Parameters register 3 " ,ACC_RW ,0x00000000 }, +{0xC10 ,"RQPRM4" ,"Receive Queue Parameters register 4 " ,ACC_RW ,0x00000000 }, +{0xC14 ,"RQPRM5" ,"Receive Queue Parameters register 5 " ,ACC_RW ,0x00000000 }, +{0xC18 ,"RQPRM6" ,"Receive Queue Parameters register 6 " ,ACC_RW ,0x00000000 }, +{0xC1C ,"RQPRM7" ,"Receive Queue Parameters register 7 " ,ACC_RW ,0x00000000 }, +{0xC44 ,"RFBPTR0" ,"Last Free RxBD pointer for ring 0" ,ACC_RW ,0x00000000 }, +{0xC4C ,"RFBPTR1" ,"Last Free RxBD pointer for ring 1" ,ACC_RW ,0x00000000 }, +{0xC54 ,"RFBPTR2" ,"Last Free RxBD pointer for ring 2" ,ACC_RW ,0x00000000 }, +{0xC5C ,"RFBPTR3" ,"Last Free RxBD pointer for ring 3" ,ACC_RW ,0x00000000 }, +{0xC64 ,"RFBPTR4" ,"Last Free RxBD pointer for ring 4" ,ACC_RW ,0x00000000 }, +{0xC6C ,"RFBPTR5" ,"Last Free RxBD pointer for ring 5" ,ACC_RW ,0x00000000 }, +{0xC74 ,"RFBPTR6" ,"Last Free RxBD pointer for ring 6" ,ACC_RW ,0x00000000 }, +{0xC7C ,"RFBPTR7" ,"Last Free RxBD pointer for ring 7" ,ACC_RW ,0x00000000 }, + +/* eTSEC Future Expansion Space */ + +/* Reserved*/ + +/* eTSEC IEEE 1588 Registers */ + +{0xE00 ,"TMR_CTRL" ,"Timer control register" ,ACC_RW ,0x00010001 }, +{0xE04 ,"TMR_TEVENT" ,"time stamp event register" , ACC_w1c,0x00000000 }, +{0xE08 ,"TMR_TEMASK" ,"Timer event mask register" ,ACC_RW ,0x00000000 }, +{0xE0C ,"TMR_PEVENT" ,"time stamp event register" ,ACC_RW ,0x00000000 }, +{0xE10 ,"TMR_PEMASK" ,"Timer event mask register" ,ACC_RW ,0x00000000 }, +{0xE14 ,"TMR_STAT" ,"time stamp status register" ,ACC_RW ,0x00000000 }, +{0xE18 ,"TMR_CNT_H" ,"timer counter high register" ,ACC_RW ,0x00000000 }, +{0xE1C ,"TMR_CNT_L" ,"timer counter low register" ,ACC_RW ,0x00000000 }, +{0xE20 ,"TMR_ADD" ,"Timer drift compensation addend register" ,ACC_RW ,0x00000000 }, +{0xE24 ,"TMR_ACC" ,"Timer accumulator register" ,ACC_RW ,0x00000000 }, +{0xE28 ,"TMR_PRSC" ,"Timer prescale" ,ACC_RW ,0x00000002 }, +{0xE30 ,"TMROFF_H" ,"Timer offset high" ,ACC_RW ,0x00000000 }, +{0xE34 ,"TMROFF_L" ,"Timer offset low" ,ACC_RW ,0x00000000 }, +{0xE40 ,"TMR_ALARM1_H" ,"Timer alarm 1 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE44 ,"TMR_ALARM1_L" ,"Timer alarm 1 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE48 ,"TMR_ALARM2_H" ,"Timer alarm 2 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE4C ,"TMR_ALARM2_L" ,"Timer alarm 2 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE80 ,"TMR_FIPER1" ,"Timer fixed period interval" ,ACC_RW ,0xFFFFFFFF }, +{0xE84 ,"TMR_FIPER2" ,"Timer fixed period interval" ,ACC_RW ,0xFFFFFFFF }, +{0xE88 ,"TMR_FIPER3" ,"Timer fixed period interval" ,ACC_RW ,0xFFFFFFFF }, +{0xEA0 ,"TMR_ETTS1_H" ,"Time stamp of general purpose external trigger " ,ACC_RW ,0x00000000 }, +{0xEA4 ,"TMR_ETTS1_L" ,"Time stamp of general purpose external trigger" ,ACC_RW ,0x00000000 }, +{0xEA8 ,"TMR_ETTS2_H" ,"Time stamp of general purpose external trigger " ,ACC_RW ,0x00000000 }, +{0xEAC ,"TMR_ETTS2_L" ,"Time stamp of general purpose external trigger" ,ACC_RW ,0x00000000 }, + +/* End Of Table */ +{0x0 ,0x0 ,0x0 ,0x0 ,0x0 } +};hw/net/etsec_registers.h new file +302
-0@@ -0,0 +1,302 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef _ETSEC_REGISTERS_H_ +#define _ETSEC_REGISTERS_H_ + +#include <stdint.h> + +typedef struct eTSEC_Register_Definition { +uint32_t offset; +const char *name; +const char *desc; +uint32_t access; +uint32_t reset; +}eTSEC_Register_Definition ; + +#define ACC_RW 1/* Read/Write */ +#define ACC_RO 2/* Read Only */ +#define ACC_WO 3/* Write Only */ +#define ACC_w1c 4/* Write 1 to clear */ +#define ACC_UNKNOWN 4/* Unknown register*/ + +extern const eTSEC_Register_Definition eTSEC_registers_def[]; + +#define DMACTRL_LE (1 << 15) +#define DMACTRL_GRS (1 << 4) +#define DMACTRL_GTS (1 << 3) +#define DMACTRL_WOP (1 << 0) + +#define IEVENT_RXF (1 << 7) +#define IEVENT_GRSC (1 << 8) +#define IEVENT_RXB (1 << 15) +#define IEVENT_TXF (1 << 20) +#define IEVENT_TXB (1 << 21) +#define IEVENT_TXC (1 << 23) +#define IEVENT_GTSC (1 << 25) +#define IEVENT_BSY (1 << 29) +#define IEVENT_RXC (1 << 30) + +#define IMASK_RXFEN (1 << 7) +#define IMASK_GRSCEN (1 << 8) +#define IMASK_RXBEN (1 << 15) +#define IMASK_TXFEN (1 << 20) +#define IMASK_TXBEN (1 << 21) +#define IMASK_GTSCEN (1 << 25) + +#define MACCFG1_TX_EN (1 << 0) +#define MACCFG1_RX_EN (1 << 2) + +#define MACCFG2_CRC_EN (1 << 1) +#define MACCFG2_PADCRC (1 << 2) + +#define MIIMCOM_READ (1 << 0) +#define MIIMCOM_SCAN (1 << 1) + +#define RCTRL_PRSDEP_MASK (0x3) +#define RCTRL_PRSDEP_OFFSET (6) +#define RCTRL_RSF (1 << 2) + +/* Index of each register */ + +#define TSEC_ID (0x000 / 4) +#define TSEC_ID2 (0x004 / 4) +#define IEVENT (0x010 / 4) +#define IMASK (0x014 / 4) +#define EDIS (0x018 / 4) +#define ECNTRL (0x020 / 4) +#define PTV (0x028 / 4) +#define DMACTRL (0x02C / 4) +#define TBIPA (0x030 / 4) +#define TCTRL (0x100 / 4) +#define TSTAT (0x104 / 4) +#define DFVLAN (0x108 / 4) +#define TXIC (0x110 / 4) +#define TQUEUE (0x114 / 4) +#define TR03WT (0x140 / 4) +#define TR47WT (0x144 / 4) +#define TBDBPH (0x180 / 4) +#define TBPTR0 (0x184 / 4) +#define TBPTR1 (0x18C / 4) +#define TBPTR2 (0x194 / 4) +#define TBPTR3 (0x19C / 4) +#define TBPTR4 (0x1A4 / 4) +#define TBPTR5 (0x1AC / 4) +#define TBPTR6 (0x1B4 / 4) +#define TBPTR7 (0x1BC / 4) +#define TBASEH (0x200 / 4) +#define TBASE0 (0x204 / 4) +#define TBASE1 (0x20C / 4) +#define TBASE2 (0x214 / 4) +#define TBASE3 (0x21C / 4) +#define TBASE4 (0x224 / 4) +#define TBASE5 (0x22C / 4) +#define TBASE6 (0x234 / 4) +#define TBASE7 (0x23C / 4) +#define TMR_TXTS1_ID (0x280 / 4) +#define TMR_TXTS2_ID (0x284 / 4) +#define TMR_TXTS1_H (0x2C0 / 4) +#define TMR_TXTS1_L (0x2C4 / 4) +#define TMR_TXTS2_H (0x2C8 / 4) +#define TMR_TXTS2_L (0x2CC / 4) +#define RCTRL (0x300 / 4) +#define RSTAT (0x304 / 4) +#define RXIC (0x310 / 4) +#define RQUEUE (0x314 / 4) +#define RBIFX (0x330 / 4) +#define RQFAR (0x334 / 4) +#define RQFCR (0x338 / 4) +#define RQFPR (0x33C / 4) +#define MRBLR (0x340 / 4) +#define RBDBPH (0x380 / 4) +#define RBPTR0 (0x384 / 4) +#define RBPTR1 (0x38C / 4) +#define RBPTR2 (0x394 / 4) +#define RBPTR3 (0x39C / 4) +#define RBPTR4 (0x3A4 / 4) +#define RBPTR5 (0x3AC / 4) +#define RBPTR6 (0x3B4 / 4) +#define RBPTR7 (0x3BC / 4) +#define RBASEH (0x400 / 4) +#define RBASE0 (0x404 / 4) +#define RBASE1 (0x40C / 4) +#define RBASE2 (0x414 / 4) +#define RBASE3 (0x41C / 4) +#define RBASE4 (0x424 / 4) +#define RBASE5 (0x42C / 4) +#define RBASE6 (0x434 / 4) +#define RBASE7 (0x43C / 4) +#define TMR_RXTS_H (0x4C0 / 4) +#define TMR_RXTS_L (0x4C4 / 4) +#define MACCFG1 (0x500 / 4) +#define MACCFG2 (0x504 / 4) +#define IPGIFG (0x508 / 4) +#define HAFDUP (0x50C / 4) +#define MAXFRM (0x510 / 4) +#define MIIMCFG (0x520 / 4) +#define MIIMCOM (0x524 / 4) +#define MIIMADD (0x528 / 4) +#define MIIMCON (0x52C / 4) +#define MIIMSTAT (0x530 / 4) +#define MIIMIND (0x534 / 4) +#define IFSTAT (0x53C / 4) +#define MACSTNADDR1 (0x540 / 4) +#define MACSTNADDR2 (0x544 / 4) +#define MAC01ADDR1 (0x548 / 4) +#define MAC01ADDR2 (0x54C / 4) +#define MAC02ADDR1 (0x550 / 4) +#define MAC02ADDR2 (0x554 / 4) +#define MAC03ADDR1 (0x558 / 4) +#define MAC03ADDR2 (0x55C / 4) +#define MAC04ADDR1 (0x560 / 4) +#define MAC04ADDR2 (0x564 / 4) +#define MAC05ADDR1 (0x568 / 4) +#define MAC05ADDR2 (0x56C / 4) +#define MAC06ADDR1 (0x570 / 4) +#define MAC06ADDR2 (0x574 / 4) +#define MAC07ADDR1 (0x578 / 4) +#define MAC07ADDR2 (0x57C / 4) +#define MAC08ADDR1 (0x580 / 4) +#define MAC08ADDR2 (0x584 / 4) +#define MAC09ADDR1 (0x588 / 4) +#define MAC09ADDR2 (0x58C / 4) +#define MAC10ADDR1 (0x590 / 4) +#define MAC10ADDR2 (0x594 / 4) +#define MAC11ADDR1 (0x598 / 4) +#define MAC11ADDR2 (0x59C / 4) +#define MAC12ADDR1 (0x5A0 / 4) +#define MAC12ADDR2 (0x5A4 / 4) +#define MAC13ADDR1 (0x5A8 / 4) +#define MAC13ADDR2 (0x5AC / 4) +#define MAC14ADDR1 (0x5B0 / 4) +#define MAC14ADDR2 (0x5B4 / 4) +#define MAC15ADDR1 (0x5B8 / 4) +#define MAC15ADDR2 (0x5BC / 4) +#define TR64 (0x680 / 4) +#define TR127 (0x684 / 4) +#define TR255 (0x688 / 4) +#define TR511 (0x68C / 4) +#define TR1K (0x690 / 4) +#define TRMAX (0x694 / 4) +#define TRMGV (0x698 / 4) +#define RBYT (0x69C / 4) +#define RPKT (0x6A0 / 4) +#define RFCS (0x6A4 / 4) +#define RMCA (0x6A8 / 4) +#define RBCA (0x6AC / 4) +#define RXCF (0x6B0 / 4) +#define RXPF (0x6B4 / 4) +#define RXUO (0x6B8 / 4) +#define RALN (0x6BC / 4) +#define RFLR (0x6C0 / 4) +#define RCDE (0x6C4 / 4) +#define RCSE (0x6C8 / 4) +#define RUND (0x6CC / 4) +#define ROVR (0x6D0 / 4) +#define RFRG (0x6D4 / 4) +#define RJBR (0x6D8 / 4) +#define RDRP (0x6DC / 4) +#define TBYT (0x6E0 / 4) +#define TPKT (0x6E4 / 4) +#define TMCA (0x6E8 / 4) +#define TBCA (0x6EC / 4) +#define TXPF (0x6F0 / 4) +#define TDFR (0x6F4 / 4) +#define TEDF (0x6F8 / 4) +#define TSCL (0x6FC / 4) +#define TMCL (0x700 / 4) +#define TLCL (0x704 / 4) +#define TXCL (0x708 / 4) +#define TNCL (0x70C / 4) +#define TDRP (0x714 / 4) +#define TJBR (0x718 / 4) +#define TFCS (0x71C / 4) +#define TXCF (0x720 / 4) +#define TOVR (0x724 / 4) +#define TUND (0x728 / 4) +#define TFRG (0x72C / 4) +#define CAR1 (0x730 / 4) +#define CAR2 (0x734 / 4) +#define CAM1 (0x738 / 4) +#define CAM2 (0x73C / 4) +#define RREJ (0x740 / 4) +#define IGADDR0 (0x800 / 4) +#define IGADDR1 (0x804 / 4) +#define IGADDR2 (0x808 / 4) +#define IGADDR3 (0x80C / 4) +#define IGADDR4 (0x810 / 4) +#define IGADDR5 (0x814 / 4) +#define IGADDR6 (0x818 / 4) +#define IGADDR7 (0x81C / 4) +#define GADDR0 (0x880 / 4) +#define GADDR1 (0x884 / 4) +#define GADDR2 (0x888 / 4) +#define GADDR3 (0x88C / 4) +#define GADDR4 (0x890 / 4) +#define GADDR5 (0x894 / 4) +#define GADDR6 (0x898 / 4) +#define GADDR7 (0x89C / 4) +#define ATTR (0xBF8 / 4) +#define ATTRELI (0xBFC / 4) +#define RQPRM0 (0xC00 / 4) +#define RQPRM1 (0xC04 / 4) +#define RQPRM2 (0xC08 / 4) +#define RQPRM3 (0xC0C / 4) +#define RQPRM4 (0xC10 / 4) +#define RQPRM5 (0xC14 / 4) +#define RQPRM6 (0xC18 / 4) +#define RQPRM7 (0xC1C / 4) +#define RFBPTR0 (0xC44 / 4) +#define RFBPTR1 (0xC4C / 4) +#define RFBPTR2 (0xC54 / 4) +#define RFBPTR3 (0xC5C / 4) +#define RFBPTR4 (0xC64 / 4) +#define RFBPTR5 (0xC6C / 4) +#define RFBPTR6 (0xC74 / 4) +#define RFBPTR7 (0xC7C / 4) +#define TMR_CTRL (0xE00 / 4) +#define TMR_TEVENT (0xE04 / 4) +#define TMR_TEMASK (0xE08 / 4) +#define TMR_PEVENT (0xE0C / 4) +#define TMR_PEMASK (0xE10 / 4) +#define TMR_STAT (0xE14 / 4) +#define TMR_CNT_H (0xE18 / 4) +#define TMR_CNT_L (0xE1C / 4) +#define TMR_ADD (0xE20 / 4) +#define TMR_ACC (0xE24 / 4) +#define TMR_PRSC (0xE28 / 4) +#define TMROFF_H (0xE30 / 4) +#define TMROFF_L (0xE34 / 4) +#define TMR_ALARM1_H (0xE40 / 4) +#define TMR_ALARM1_L (0xE44 / 4) +#define TMR_ALARM2_H (0xE48 / 4) +#define TMR_ALARM2_L (0xE4C / 4) +#define TMR_FIPER1 (0xE80 / 4) +#define TMR_FIPER2 (0xE84 / 4) +#define TMR_FIPER3 (0xE88 / 4) +#define TMR_ETTS1_H (0xEA0 / 4) +#define TMR_ETTS1_L (0xEA4 / 4) +#define TMR_ETTS2_H (0xEA8 / 4) +#define TMR_ETTS2_L (0xEAC / 4) + +#endif /* ! _ETSEC_REGISTERS_H_ */ hw/net/etsec_rings.c new file +673
-0@@ -0,0 +1,673 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#include "qemu/bswap.h" +#include "net/checksum.h" + +#include "etsec.h" +#include "etsec_registers.h" + +/* #define ETSEC_RING_DEBUG */ +/* #define HEX_DUMP */ +/* #define DEBUG_BD */ + +#ifdef ETSEC_RING_DEBUG +#define RING_DEBUG (fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__) +#else +#define RING_DEBUG (...) +#endif /* ETSEC_RING_DEBUG */ + +#define RING_DEBUG_A (fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__) + +#ifdef DEBUG_BD + +static void print_tx_bd_flags (uint16_t flags) +{ +printf (" Ready: %d\n" , !!(flags &BD_TX_READY )); +printf (" PAD/CRC: %d\n" , !!(flags &BD_TX_PADCRC )); +printf (" Wrap: %d\n" , !!(flags &BD_WRAP )); +printf (" Interrupt: %d\n" , !!(flags &BD_INTERRUPT )); +printf (" Last in frame: %d\n" , !!(flags &BD_LAST )); +printf (" Tx CRC: %d\n" , !!(flags &BD_TX_TC )); +printf (" User-defined preamble / defer: %d\n" , + !!(flags &BD_TX_PREDEF )); +printf (" Huge frame enable / Late collision: %d\n" , + !!(flags &BD_TX_HFELC )); +printf (" Control frame / Retransmission Limit: %d\n" , + !!(flags &BD_TX_CFRL )); +printf (" Retry count: %d\n" , + (flags >>BD_TX_RC_OFFSET ) &BD_TX_RC_MASK ); +printf (" Underrun / TCP/IP off-load enable: %d\n" , + !!(flags &BD_TX_TOEUN )); +printf (" Truncation: %d\n" , !!(flags &BD_TX_TR )); +} + +static void print_rx_bd_flags (uint16_t flags) +{ +printf (" Empty: %d\n" , !!(flags &BD_RX_EMPTY )); +printf (" Receive software ownership: %d\n" , !!(flags &BD_RX_RO1 )); +printf (" Wrap: %d\n" , !!(flags &BD_WRAP )); +printf (" Interrupt: %d\n" , !!(flags &BD_INTERRUPT )); +printf (" Last in frame: %d\n" , !!(flags &BD_LAST )); +printf (" First in frame: %d\n" , !!(flags &BD_RX_FIRST )); +printf (" Miss: %d\n" , !!(flags &BD_RX_MISS )); +printf (" Broadcast: %d\n" , !!(flags &BD_RX_BROADCAST )); +printf (" Multicast: %d\n" , !!(flags &BD_RX_MULTICAST )); +printf (" Rx frame length violation: %d\n" , !!(flags &BD_RX_LG )); +printf (" Rx non-octet aligned frame: %d\n" , !!(flags &BD_RX_NO )); +printf (" Short frame: %d\n" , !!(flags &BD_RX_SH )); +printf (" Rx CRC Error: %d\n" , !!(flags &BD_RX_CR )); +printf (" Overrun: %d\n" , !!(flags &BD_RX_OV )); +printf (" Truncation: %d\n" , !!(flags &BD_RX_TR )); +} + + +static void print_bd (eTSEC_rxtx_bd bd,int mode,uint32_t index) +{ +printf ("eTSEC %s Data Buffer Descriptor (%u)\n" , + mode == eTSEC_TRANSMIT ?"Transmit" :"Receive" , + index); +printf (" Flags : 0x%04x\n" , bd.flags); +if (mode == eTSEC_TRANSMIT) { +print_tx_bd_flags (bd.flags); + }else { +print_rx_bd_flags (bd.flags); + } +printf (" Length : 0x%04x\n" , bd.length); +printf (" Pointer : 0x%08x\n" , bd.bufptr); +} + +#endif /* DEBUG_BD */ + +#ifdef HEX_DUMP + +static void hex_dump (FILE *f,const uint8_t *buf,int size) +{ +int len, i, j, c; + +for (i =0 ; i < size; i +=16 ) { + len = size - i; +if (len >16 ) { + len =16 ; + } +fprintf (f,"%08x " , i); +for (j =0 ; j <16 ; j++) { +if (j < len) { +fprintf (f," %02x" , buf[i + j]); + }else { +fprintf (f," " ); + } + } +fprintf (f," " ); +for (j =0 ; j < len; j++) { + c = buf[i + j]; +if (c <' ' || c >'~' ) { + c ='.' ; + } +fprintf (f,"%c" , c); + } +fprintf (f,"\n" ); + } +} + +#endif + +static void read_buffer_descriptor (eTSEC *etsec, +hwaddr addr, +eTSEC_rxtx_bd *bd) +{ +assert (bd !=NULL ); + +RING_DEBUG ("READ Buffer Descriptor @ 0x" TARGET_FMT_plx"\n" , addr); +cpu_physical_memory_read (addr, + bd, +sizeof (eTSEC_rxtx_bd)); + +if (etsec->regs[DMACTRL ].value &DMACTRL_LE ) { + bd->flags =le16_to_cpupu (&bd->flags); + bd->length =le16_to_cpupu (&bd->length); + bd->bufptr =le32_to_cpupu (&bd->bufptr); + }else { + bd->flags =be16_to_cpupu (&bd->flags); + bd->length =be16_to_cpupu (&bd->length); + bd->bufptr =be32_to_cpupu (&bd->bufptr); + } +} + +static void write_buffer_descriptor (eTSEC *etsec, +hwaddr addr, +eTSEC_rxtx_bd *bd) +{ +assert (bd !=NULL ); + +if (etsec->regs[DMACTRL ].value &DMACTRL_LE ) { +cpu_to_le16wu (&bd->flags, bd->flags); +cpu_to_le16wu (&bd->length, bd->length); +cpu_to_le32wu (&bd->bufptr, bd->bufptr); + }else { +cpu_to_be16wu (&bd->flags, bd->flags); +cpu_to_be16wu (&bd->length, bd->length); +cpu_to_be32wu (&bd->bufptr, bd->bufptr); + } + +RING_DEBUG ("Write Buffer Descriptor @ 0x" TARGET_FMT_plx"\n" , addr); +cpu_physical_memory_write (addr, + bd, +sizeof (eTSEC_rxtx_bd)); +} + +static void ievent_set (eTSEC *etsec, +uint32_t flags) +{ + etsec->regs[IEVENT ].value |= flags; + +if ((flags &IEVENT_TXB && etsec->regs[IMASK ].value &IMASK_TXBEN ) + || (flags &IEVENT_TXF && etsec->regs[IMASK ].value &IMASK_TXFEN )) { +qemu_irq_raise (etsec->tx_irq); +RING_DEBUG ("%s Raise Tx IRQ\n" , __func__); + } + +if ((flags &IEVENT_RXB && etsec->regs[IMASK ].value &IMASK_RXBEN ) + || (flags &IEVENT_RXF && etsec->regs[IMASK ].value &IMASK_RXFEN )) { +qemu_irq_pulse (etsec->rx_irq); +RING_DEBUG ("%s Raise Rx IRQ\n" , __func__); + } +} + +static void tx_padding_and_crc (eTSEC *etsec,uint32_t min_frame_len) +{ +int add = min_frame_len - etsec->tx_buffer_len; + +/* Padding */ +if (add >0 ) { +RING_DEBUG ("pad:%u\n" , add); + etsec->tx_buffer =g_realloc (etsec->tx_buffer, + etsec->tx_buffer_len + add); + +memset (etsec->tx_buffer + etsec->tx_buffer_len,0x0 , add); + etsec->tx_buffer_len += add; + } + +/* Never add CRC in QEMU */ +} + +static void process_tx_fcb (eTSEC *etsec) +{ +uint8_t flags = (uint8_t )(*etsec->tx_buffer); +/* L3 header offset from start of frame */ +uint8_t l3_header_offset = (uint8_t )*(etsec->tx_buffer +3 ); +/* L4 header offset from start of L3 header */ +uint8_t l4_header_offset = (uint8_t )*(etsec->tx_buffer +2 ); +/* L3 header */ +uint8_t *l3_header = etsec->tx_buffer +8 + l3_header_offset; +/* L4 header */ +uint8_t *l4_header = l3_header + l4_header_offset; + +/* if packet is IP4 and IP checksum is requested */ +if (flags &FCB_TX_IP && flags &FCB_TX_CIP ) { +/* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure +* if it also does IP4 checksum. */ +net_checksum_calculate (etsec->tx_buffer +8 , + etsec->tx_buffer_len -8 ); + } +/* TODO Check the correct usage of the PHCS field of the FCB in case the NPH +* flag is on */ + +/* if packet is IP4 and TCP or UDP */ +if (flags &FCB_TX_IP && flags &FCB_TX_TUP ) { +/* if UDP */ +if (flags &FCB_TX_UDP ) { +/* if checksum is requested */ +if (flags &FCB_TX_CTU ) { +/* do UDP checksum */ + +net_checksum_calculate (etsec->tx_buffer +8 , + etsec->tx_buffer_len -8 ); + }else { +/* set checksum field to 0 */ + l4_header[6 ] =0 ; + l4_header[7 ] =0 ; + } + }else if (flags &FCB_TX_CTU ) {/* if TCP and checksum is requested */ +/* do TCP checksum */ +net_checksum_calculate (etsec->tx_buffer +8 , + etsec->tx_buffer_len -8 ); + } + } +} + +static void process_tx_bd (eTSEC *etsec, +eTSEC_rxtx_bd *bd) +{ +uint8_t *tmp_buff =NULL ; + +if (bd->length ==0 ) { +/* ERROR */ +return ; + } + +if (etsec->tx_buffer_len ==0 ) { +/* It's the first BD */ + etsec->first_bd = *bd; + } + +/* TODO: if TxBD[TOE/UN] skip the Tx Frame Control Block*/ + +/* Load this Data Buffer */ + etsec->tx_buffer =g_realloc (etsec->tx_buffer, + etsec->tx_buffer_len + bd->length); + tmp_buff = etsec->tx_buffer + etsec->tx_buffer_len; +cpu_physical_memory_read (bd->bufptr, tmp_buff, bd->length); + +/* Update buffer length */ + etsec->tx_buffer_len += bd->length; + + +if (etsec->tx_buffer_len !=0 && (bd->flags &BD_LAST )) { +if (etsec->regs[MACCFG1 ].value &MACCFG1_TX_EN ) { +/* MAC Transmit enabled */ + +/* Process offload Tx FCB */ +if (etsec->first_bd.flags &BD_TX_TOEUN ) { +process_tx_fcb (etsec); + } + +if (etsec->first_bd.flags &BD_TX_PADCRC + || etsec->regs[MACCFG2 ].value &MACCFG2_PADCRC ) { + +/* Padding and CRC (Padding implies CRC) */ +tx_padding_and_crc (etsec,64 ); + + }else if (etsec->first_bd.flags &BD_TX_TC + || etsec->regs[MACCFG2 ].value &MACCFG2_CRC_EN ) { + +/* Only CRC */ +/* Never add CRC in QEMU */ + } + +#if defined(HEX_DUMP ) +fprintf (stderr,"eTSEC Send packet size:%d\n" , + etsec->tx_buffer_len); +hex_dump (stderr, etsec->tx_buffer, etsec->tx_buffer_len); +#endif /* ETSEC_RING_DEBUG */ + +if (etsec->first_bd.flags &BD_TX_TOEUN ) { +qemu_send_packet (qemu_get_queue (etsec->nic), + etsec->tx_buffer +8 , + etsec->tx_buffer_len -8 ); + }else { +qemu_send_packet (qemu_get_queue (etsec->nic), + etsec->tx_buffer, + etsec->tx_buffer_len); + } + + } + + etsec->tx_buffer_len =0 ; + +if (bd->flags &BD_INTERRUPT ) { +ievent_set (etsec,IEVENT_TXF ); + } + }else { +if (bd->flags &BD_INTERRUPT ) { +ievent_set (etsec,IEVENT_TXB ); + } + } + +/* Update DB flags */ + +/* Clear Ready */ + bd->flags &= ~BD_TX_READY ; + +/* Clear Defer */ + bd->flags &= ~BD_TX_PREDEF ; + +/* Clear Late Collision */ + bd->flags &= ~BD_TX_HFELC ; + +/* Clear Retransmission Limit */ + bd->flags &= ~BD_TX_CFRL ; + +/* Clear Retry Count */ + bd->flags &= ~(BD_TX_RC_MASK <<BD_TX_RC_OFFSET ); + +/* Clear Underrun */ + bd->flags &= ~BD_TX_TOEUN ; + +/* Clear Truncation */ + bd->flags &= ~BD_TX_TR ; +} + +void walk_tx_ring (eTSEC *etsec,int ring_nbr) +{ +hwaddr ring_base =0 ; +hwaddr bd_addr =0 ; +eTSEC_rxtx_bd bd; +uint16_t bd_flags; + +if (!(etsec->regs[MACCFG1 ].value &MACCFG1_TX_EN )) { +RING_DEBUG ("%s: MAC Transmit not enabled\n" , __func__); +return ; + } + +/* ring_base = (etsec->regs[TBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[TBASE0 + ring_nbr].value & ~0x7 ; + bd_addr = etsec->regs[TBPTR0 + ring_nbr].value & ~0x7 ; + +do { +read_buffer_descriptor (etsec, bd_addr, &bd); + +#ifdef DEBUG_BD +print_bd (bd, + eTSEC_TRANSMIT, + (bd_addr - ring_base) /sizeof (eTSEC_rxtx_bd)); + +#endif /* DEBUG_BD */ + +/* Save flags before BD update */ + bd_flags = bd.flags; + +if (bd_flags &BD_TX_READY ) { +process_tx_bd (etsec, &bd); + +/* Write back BD after update */ +write_buffer_descriptor (etsec, bd_addr, &bd); + } + +/* Wrap or next BD */ +if (bd_flags &BD_WRAP ) { + bd_addr = ring_base; + }else { + bd_addr +=sizeof (eTSEC_rxtx_bd); + } + + }while (bd_addr != ring_base); + + bd_addr = ring_base; + +/* Save the Buffer Descriptor Pointers to current bd */ + etsec->regs[TBPTR0 + ring_nbr].value = bd_addr; + +/* Set transmit halt THLTx */ + etsec->regs[TSTAT ].value |=1 << (31 - ring_nbr); +} + +static void fill_rx_bd (eTSEC *etsec, +eTSEC_rxtx_bd *bd, +const uint8_t **buf, +size_t *size) +{ +uint16_t to_write =MIN (etsec->rx_fcb_size + *size - etsec->rx_padding, + etsec->regs[MRBLR ].value); +uint32_t bufptr = bd->bufptr; +uint8_t padd[etsec->rx_padding]; +uint8_t rem; + +RING_DEBUG ("eTSEC fill Rx buffer @ 0x%08x" +" size:%u(padding + crc:%u) + fcb:%u\n" , + bufptr, *size, etsec->rx_padding, etsec->rx_fcb_size); + + bd->length =0 ; +if (etsec->rx_fcb_size !=0 ) { +cpu_physical_memory_write (bufptr, etsec->rx_fcb, etsec->rx_fcb_size); + + bufptr += etsec->rx_fcb_size; + bd->length += etsec->rx_fcb_size; + to_write -= etsec->rx_fcb_size; + etsec->rx_fcb_size =0 ; + + } + +if (to_write >0 ) { +cpu_physical_memory_write (bufptr, *buf, to_write); + + *buf += to_write; + bufptr += to_write; + *size -= to_write; + + bd->flags &= ~BD_RX_EMPTY ; + bd->length += to_write; + } + +if (*size == etsec->rx_padding) { +/* The remaining bytes are for padding which is not actually allocated +in the buffer */ + + rem =MIN (etsec->regs[MRBLR ].value - bd->length, etsec->rx_padding); + +if (rem >0 ) { +memset (padd,0x0 ,sizeof (padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; +cpu_physical_memory_write (bufptr, padd, rem); + } + } +} + +static void rx_init_frame (eTSEC *etsec,const uint8_t *buf,size_t size) +{ +uint32_t fcb_size =0 ; +uint8_t prsdep = (etsec->regs[RCTRL ].value >>RCTRL_PRSDEP_OFFSET ) + &RCTRL_PRSDEP_MASK ; + +if (prsdep !=0 ) { +/* Prepend FCB */ + fcb_size =8 +2 ;/* FCB size + align */ +/* I can't find this 2 bytes alignement in fsl documentation but VxWorks +expects them */ + + etsec->rx_fcb_size = fcb_size; + +/* TODO: fill_FCB(etsec); */ +memset (etsec->rx_fcb,0x0 ,sizeof (etsec->rx_fcb)); + + }else { + etsec->rx_fcb_size =0 ; + } + +if (etsec->rx_buffer !=NULL ) { +g_free (etsec->rx_buffer); + } + +/* Do not copy the frame for now */ + etsec->rx_buffer = (uint8_t *)buf; + etsec->rx_buffer_len = size; + etsec->rx_padding =4 ; + +if (size <60 ) { + etsec->rx_padding +=60 - size; + } + + etsec->rx_first_in_frame =1 ; + etsec->rx_remaining_data = etsec->rx_buffer_len; +RING_DEBUG ("%s: rx_buffer_len:%u rx_padding+crc:%u\n" , __func__, + etsec->rx_buffer_len, etsec->rx_padding); +} + +void rx_ring_write (eTSEC *etsec,const uint8_t *buf,size_t size) +{ +int ring_nbr =0 ;/* Always use ring0 (no filer) */ + +if (etsec->rx_buffer_len !=0 ) { +RING_DEBUG ("%s: We can't receive now," +" a buffer is already in the pipe\n" , __func__); +return ; + } + +if (etsec->regs[RSTAT ].value &1 << (23 - ring_nbr)) { +RING_DEBUG ("%s: The ring is halted\n" , __func__); +return ; + } + +if (etsec->regs[DMACTRL ].value &DMACTRL_GRS ) { +RING_DEBUG ("%s: Graceful receive stop\n" , __func__); +return ; + } + +if (!(etsec->regs[MACCFG1 ].value &MACCFG1_RX_EN )) { +RING_DEBUG ("%s: MAC Receive not enabled\n" , __func__); +return ; + } + +/* Don't drop short packets, just add padding (later) */ + +rx_init_frame (etsec, buf, size); + +walk_rx_ring (etsec, ring_nbr); +} + +void walk_rx_ring (eTSEC *etsec,int ring_nbr) +{ +hwaddr ring_base =0 ; +hwaddr bd_addr =0 ; +hwaddr start_bd_addr =0 ; +eTSEC_rxtx_bd bd; +uint16_t bd_flags; +size_t remaining_data; +const uint8_t *buf; +uint8_t *tmp_buf; +size_t size; + +if (etsec->rx_buffer_len ==0 ) { +/* No frame to send */ +RING_DEBUG ("No frame to send\n" ); +return ; + } + + remaining_data = etsec->rx_remaining_data + etsec->rx_padding; + buf = etsec->rx_buffer + + (etsec->rx_buffer_len - etsec->rx_remaining_data); + size = etsec->rx_buffer_len + etsec->rx_padding; + +/* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7 ; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7 ; + +do { +read_buffer_descriptor (etsec, bd_addr, &bd); + +#ifdef DEBUG_BD +print_bd (bd, + eTSEC_RECEIVE, + (bd_addr - ring_base) /sizeof (eTSEC_rxtx_bd)); + +#endif /* DEBUG_BD */ + +/* Save flags before BD update */ + bd_flags = bd.flags; + +if (bd_flags &BD_RX_EMPTY ) { +fill_rx_bd (etsec, &bd, &buf, &remaining_data); + +if (etsec->rx_first_in_frame) { + bd.flags |=BD_RX_FIRST ; + etsec->rx_first_in_frame =0 ; + etsec->rx_first_bd = bd; + } + +/* Last in frame */ +if (remaining_data ==0 ) { + +/* Clear flags */ + + bd.flags &= ~0x7ff ; + + bd.flags |=BD_LAST ; + +/* NOTE: non-octet aligned frame is impossible in qemu */ + +if (size >= etsec->regs[MAXFRM ].value) { +/* frame length violation */ +printf ("%s frame length violation: size:%d MAXFRM:%d\n" , + __func__, size, etsec->regs[MAXFRM ].value); + + bd.flags |=BD_RX_LG ; + } + +if (size <64 ) { +/* Short frame */ +printf ("%s Short frame: %d\n" , __func__, size); + bd.flags |=BD_RX_SH ; + } + +/* TODO: Broadcast and Multicast */ + +if (bd.flags |BD_INTERRUPT ) { +/* Set RXFx */ + etsec->regs[RSTAT ].value |=1 << (7 - ring_nbr); + +/* Set IEVENT */ +ievent_set (etsec,IEVENT_RXF ); + } + + }else { +if (bd.flags |BD_INTERRUPT ) { +/* Set IEVENT */ +ievent_set (etsec,IEVENT_RXB ); + } + } + +/* Write back BD after update */ +write_buffer_descriptor (etsec, bd_addr, &bd); + } + +/* Wrap or next BD */ +if (bd_flags &BD_WRAP ) { + bd_addr = ring_base; + }else { + bd_addr +=sizeof (eTSEC_rxtx_bd); + } + }while (remaining_data !=0 + && (bd_flags &BD_RX_EMPTY ) + && bd_addr != start_bd_addr); + +/* Reset ring ptr */ + etsec->regs[RBPTR0 + ring_nbr].value = bd_addr; + +/* The frame is too large to fit in the Rx ring */ +if (remaining_data >0 ) { + +/* Set RSTAT[QHLTx] */ + etsec->regs[RSTAT ].value |=1 << (23 - ring_nbr); + +/* Save remaining data to send the end of the frame when the ring will +* be restarted +*/ + etsec->rx_remaining_data = remaining_data; + +/* Copy the frame */ + tmp_buf =g_malloc (size); +memcpy (tmp_buf, etsec->rx_buffer, size); + etsec->rx_buffer = tmp_buf; + +RING_DEBUG ("no empty RxBD available any more\n" ); + }else { + etsec->rx_buffer_len =0 ; + etsec->rx_buffer =NULL ; + } + +RING_DEBUG ("eTSEC End of ring_write: remaining_data:%u\n" , remaining_data); +}Signature · 1 line
1.7.9.5
Hi:
I'm very interesting in it, but I don't know how to create a eTSEC
device, I did a test as below:
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
if (!nd->model) {
nd->model = g_strdup("eTSEC");
}
if(strcmp(nd->model, "eTSEC") == 0) {
etsec_create(ETSEC0_REGS_OFFSET, ccsr_addr_space, nd,
mpic[0x1d], mpic[0x1e], mpic[0x22]);
}
}When I start the qemu, an error exists" qemu-system-ppc: Unsupported NIC model: eTSEC" . Could you tell me how to create a eTSEC device?
Thank you!
--------------------------------------------------
2013-07-15
Re: [Qemu-devel] Fw: [PATCH 2/2] Add Enhanced Three-Speed EthernetController (eTSEC)
Quoted 15 lines · Yao Xingtao
Hi:
I'm very interesting in it, but I don't know how to create a eTSEC
device, I did a test as below:for(i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; if (!nd->model) { nd->model = g_strdup("eTSEC"); } if(strcmp(nd->model, "eTSEC") == 0) { etsec_create(ETSEC0_REGS_OFFSET, ccsr_addr_space, nd, mpic[0x1d], mpic[0x1e], mpic[0x22]); } }
Quoted 3 lines
When I start the qemu, an error exists" qemu-system-ppc: Unsupported NIC model: eTSEC" . Could you tell me how to create a eTSEC device?
Maybe because your machine has a pci_nic_init_nofail() call. eTSEC is not a PCI NIC...
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
In reply to Fabien ChouteauHi Fabien,
Quoted 86 lines · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS. recieve
Signed-off-by Fabien Chouteau <[email protected]>--- default-configs/ppc-softmmu.mak | 1 + hw/net/Makefile.objs | 1 + hw/net/etsec.c | 472 +++++++++++++++++++++++++++ hw/net/etsec.h | 169 ++++++++++ hw/net/etsec_miim.c | 146 +++++++++ hw/net/etsec_registers.c | 295 +++++++++++++++++ hw/net/etsec_registers.h | 302 ++++++++++++++++++ hw/net/etsec_rings.c | 673 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 2059 insertions(+) create mode 100644 hw/net/etsec.c create mode 100644 hw/net/etsec.h create mode 100644 hw/net/etsec_miim.c create mode 100644 hw/net/etsec_registers.c create mode 100644 hw/net/etsec_registers.h create mode 100644 hw/net/etsec_rings.cdefault-configs/ppc-softmmu.mak +1
-0@@ -46,3 +46,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y +CONFIG_ETSEC=yhw/net/Makefile.objs +1
-0@@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o obj-$(CONFIG_PSERIES) += spapr_llan.o obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o obj-$(CONFIG_VIRTIO) += virtio-net.o obj-y += vhost_net.ohw/net/etsec.c new file +39
-0@@ -0,0 +1,472 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "trace.h" +#include "hw/ptimer.h" +#include "hw/net/etsec.h" +#include "hw/net/etsec_registers.h" + +/* #define HEX_DUMP */ +/* #define DEBUG_REGISTER */ + +static uint64_t etsec_read (void *opaque,hwaddr addr,unsigned size) +{ +eTSEC *etsec = opaque; +uint32_t reg_index = addr /4 ; +eTSEC_Register *reg =NULL ;
hw/net/etsec.c line 49
Quoted 10 lines
hw/net/etsec.c new file +10
-0+uint32_t ret =0x0 ; + +assert (reg_index <REG_NUMBER ); + + reg = &etsec->regs[reg_index]; + + +switch (reg->access) { +case ACC_WO : + ret =0x00000000 ;
worth a qemu_log_mask(LOG_GUEST_ERROR ?
Quoted 191 lines
hw/net/etsec.c new file +191
-0+break ; + +case ACC_RW : +case ACC_w1c: +case ACC_RO : +default : + ret = reg->value; +break ; + } + +#ifdef DEBUG_REGISTER +printf ("Read 0x%08x @ 0x" TARGET_FMT_plx +" : %s (%s)\n" , + ret, addr, reg->name, reg->desc); +#endif + +return ret; +} + +static void write_tstat (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ +int i =0 ; + +for (i =0 ; i <8 ; i++) { +/* Check THLTi flag in TSTAT */ +if (value & (1 << (31 - i))) { +walk_tx_ring (etsec, i); + } + } + +/* Write 1 to clear */ + reg->value &= ~value; +} + +static void write_rstat (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ +int i =0 ; + +for (i =0 ; i <8 ; i++) { +/* Check QHLTi flag in RSTAT */ +if (value & (1 << (23 - i)) && !(reg->value & (1 << (23 - i)))) { +walk_rx_ring (etsec, i); + } + } + +/* Write 1 to clear */ + reg->value &= ~value; +} + +static void write_tbasex (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + reg->value = value & ~0x7 ; + +/* Copy this value in the ring's TxBD pointer */ + etsec->regs[TBPTR0 + (reg_index -TBASE0 )].value = value & ~0x7 ; +} + +static void write_rbasex (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + reg->value = value & ~0x7 ; + +/* Copy this value in the ring's RxBD pointer */ + etsec->regs[RBPTR0 + (reg_index -RBASE0 )].value = value & ~0x7 ; +} + +static void write_ievent (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ +if (value &IEVENT_TXF ) { +qemu_irq_lower (etsec->tx_irq); + } +if (value &IEVENT_RXF ) { +qemu_irq_lower (etsec->rx_irq); + } + +/* Write 1 to clear */ + reg->value &= ~value; +} + +static void write_dmactrl (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + reg->value = value; + +if (value &DMACTRL_GRS ) { + +if (etsec->rx_buffer_len !=0 ) { +/* Graceful receive stop delayed until end of frame */ + }else { +/* Graceful receive stop now */ + etsec->regs[IEVENT ].value |=IEVENT_GRSC ; +if (etsec->regs[IMASK ].value &IMASK_GRSCEN ) { +qemu_irq_raise (etsec->err_irq); + } + } + } + +if (value &DMACTRL_GTS ) { + +if (etsec->tx_buffer_len !=0 ) { +/* Graceful transmit stop delayed until end of frame */ + }else { +/* Graceful transmit stop now */ + etsec->regs[IEVENT ].value |=IEVENT_GTSC ; +if (etsec->regs[IMASK ].value &IMASK_GTSCEN ) { +qemu_irq_raise (etsec->err_irq); + } + } + } + +if (!(value &DMACTRL_WOP )) { +/* Start polling */ +ptimer_stop (etsec->ptimer); +ptimer_set_count (etsec->ptimer,1 ); +ptimer_run (etsec->ptimer,1 ); + } +} + +static void etsec_write (void *opaque, +hwaddr addr, +uint64_t value, +unsigned size) +{ +eTSEC *etsec = opaque; +uint32_t reg_index = addr /4 ; +eTSEC_Register *reg =NULL ; +uint32_t before =0x0 ; + +assert (reg_index <REG_NUMBER ); + + reg = &etsec->regs[reg_index]; + before = reg->value; + +switch (reg_index) { +case IEVENT : +write_ievent (etsec, reg, reg_index, value); +break ; + +case DMACTRL : +write_dmactrl (etsec, reg, reg_index, value); +break ; + +case TSTAT : +write_tstat (etsec, reg, reg_index, value); +break ; + +case RSTAT : +write_rstat (etsec, reg, reg_index, value); +break ; + + case TBASE0 ... TBASE7: +write_tbasex (etsec, reg, reg_index, value); +break ; + + case RBASE0 ... RBASE7: +write_rbasex (etsec, reg, reg_index, value); +break ; + + case MIIMCFG ... MIIMIND: +write_miim (etsec, reg, reg_index, value); +break ; + +default : +/* Default handling */ +switch (reg->access) { + +case ACC_RW : +case ACC_WO : + reg->value = value; +break ; + +case ACC_w1c: + reg->value &= ~value; +break ; +
hw/net/etsec.c line 250
Quoted 10 lines
hw/net/etsec.c new file +10
-0+case ACC_RO : +default : +/* Read Only or Unknown register */ +break ; + } + } + +#ifdef DEBUG_REGISTER +printf ("Write 0x%08x @ 0x" TARGET_FMT_plx" val:0x%08x->0x%08x : %s (%s)\n" , + (unsigned int )value, addr, before, reg->value, reg->name, reg->desc);
Last I knew, printf was a bad idea for error messages due to monitor interference issue and nographic mode. But qemu_log or fprintf(stderr, are both better alternatives.
Quoted 69 lines
hw/net/etsec.c new file +69
-0+#else + (void )before;/* Unreferenced */ +#endif + +} + +static const MemoryRegionOps etsec_ops = { + .read = etsec_read, + .write = etsec_write, + .endianness =DEVICE_NATIVE_ENDIAN , + .impl = { + .min_access_size =4 , + .max_access_size =4 , + }, +}; + +static void etsec_timer_hit (void *opaque) +{ +eTSEC *etsec = opaque; + +ptimer_stop (etsec->ptimer); + +if (!(etsec->regs[DMACTRL ].value &DMACTRL_WOP )) { + +if (!(etsec->regs[DMACTRL ].value &DMACTRL_GTS )) { +walk_tx_ring (etsec,0 ); + } +ptimer_set_count (etsec->ptimer,1 ); +ptimer_run (etsec->ptimer,1 ); + } +} + +static void etsec_reset (DeviceState *d) +{ +eTSEC *etsec =container_of (d, eTSEC, busdev.qdev); +int i =0 ; +int reg_index =0 ; + +/* Default value for all registers */ +for (i =0 ; i <REG_NUMBER ; i++) { + etsec->regs[i].name ="Reserved" ; + etsec->regs[i].desc ="" ; + etsec->regs[i].access =ACC_UNKNOWN ; + etsec->regs[i].value =0x00000000 ; + } + +/* Set-up known registers */ +for (i =0 ; eTSEC_registers_def[i].name !=NULL ; i++) { + + reg_index = eTSEC_registers_def[i].offset /4 ; + + etsec->regs[reg_index].name = eTSEC_registers_def[i].name; + etsec->regs[reg_index].desc = eTSEC_registers_def[i].desc; + etsec->regs[reg_index].access = eTSEC_registers_def[i].access; + etsec->regs[reg_index].value = eTSEC_registers_def[i].reset; + } + + etsec->tx_buffer =NULL ; + etsec->tx_buffer_len =0 ; + etsec->rx_buffer =NULL ; + etsec->rx_buffer_len =0 ; + + etsec->phy_status = +MII_SR_EXTENDED_CAPS |MII_SR_LINK_STATUS |MII_SR_AUTONEG_CAPS | +MII_SR_AUTONEG_COMPLETE |MII_SR_PREAMBLE_SUPPRESS | +MII_SR_EXTENDED_STATUS |MII_SR_100T2_HD_CAPS |MII_SR_100T2_FD_CAPS | +MII_SR_10T_HD_CAPS |MII_SR_10T_FD_CAPS |MII_SR_100X_HD_CAPS | +MII_SR_100X_FD_CAPS |MII_SR_100T4_CAPS ; +}
hw/net/etsec.c line 329
Quoted 10 lines
hw/net/etsec.c new file +10
-0+ +static void etsec_cleanup (NetClientState *nc) +{ +/* printf("eTSEC cleanup\n"); */ +} + +static int etsec_can_receive (NetClientState *nc) +{ +/* Yes we always can\ */ +return 1 ;
As a general rule this is a bad idea. Multiple ethernet controllers in QEMU have tried this and had issues (particularly with the UBOOT bootloader) with mass packet droppage. But You have access to the information needed (the if conditions in rx_ring_write) to implement this it seems.
Quoted 57 lines
hw/net/etsec.c new file +57
-0+} + +#ifdef HEX_DUMP +static void hex_dump (FILE *f,const uint8_t *buf,int size) +{ +int len, i, j, c; + +for (i =0 ; i < size; i +=16 ) { + len = size - i; +if (len >16 ) { + len =16 ; + } +fprintf (f,"%08x " , i); +for (j =0 ; j <16 ; j++) { +if (j < len) { +fprintf (f," %02x" , buf[i + j]); + }else { +fprintf (f," " ); + } + } +fprintf (f," " ); +for (j =0 ; j < len; j++) { + c = buf[i + j]; +if (c <' ' || c >'~' ) { + c ='.' ; + } +fprintf (f,"%c" , c); + } +fprintf (f,"\n" ); + } +} +#endif + +static ssize_t etsec_receive (NetClientState *nc, +const uint8_t *buf, +size_t size) +{ +eTSEC *etsec =qemu_get_nic_opaque (nc); + +#if defined(HEX_DUMP ) +fprintf (stderr,"%s receive size:%d\n" , etsec->nic->nc.name, size); +hex_dump (stderr, buf, size); +#endif +rx_ring_write (etsec, buf, size); +return size; +} + + +static void etsec_set_link_status (NetClientState *nc) +{ +eTSEC *etsec =qemu_get_nic_opaque (nc); + +miim_link_status (etsec, nc); +} + +static NetClientInfo net_etsec_info = { + .type =NET_CLIENT_OPTIONS_KIND_NIC ,
hw/net/etsec.c line 396
Quoted 10 lines
hw/net/etsec.c new file +10
-0+ .size = sizeof(NICState), + .can_receive = etsec_can_receive, + .receive = etsec_receive, + .cleanup = etsec_cleanup, + .link_status_changed = etsec_set_link_status, +}; + +static int etsec_init (SysBusDevice *dev) +{ +eTSEC *etsec =FROM_SYSBUS (typeof (*etsec), dev);
Define and use QOM cast macros instead, FROM_FOO macros are deprecated.
hw/net/etsec.c line 399
Quoted 3 lines
hw/net/etsec.c new file +3
-0+ +memory_region_init_io (&etsec->io_area,OBJECT (etsec), &etsec_ops, etsec, +"eTSEC" ,0x1000 );
Constant size memory_region_init_io should be migrated to the Object::Init fm.
Quoted 20 lines
hw/net/etsec.c new file +20
-0+ +sysbus_init_mmio (dev, &etsec->io_area); + +sysbus_init_irq (dev, &etsec->tx_irq); +sysbus_init_irq (dev, &etsec->rx_irq); +sysbus_init_irq (dev, &etsec->err_irq); + + etsec->nic =qemu_new_nic (&net_etsec_info, &etsec->conf, +"eTSEC" , etsec->busdev.qdev.id, etsec); +qemu_format_nic_info_str (qemu_get_queue (etsec->nic), etsec->conf.macaddr.a); + + + etsec->bh =qemu_bh_new (etsec_timer_hit, etsec); + etsec->ptimer =ptimer_init (etsec->bh); +ptimer_set_freq (etsec->ptimer,100 ); + +return 0 ; +} + +static Property etsec_properties[] = {
hw/net/etsec.c line 429
Quoted 10 lines
hw/net/etsec.c new file +10
-0+DEFINE_NIC_PROPERTIES (eTSEC, conf), + DEFINE_PROP_END_OF_LIST(), +}; + +static void etsec_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = etsec_init;
SysBusDevice::init in depracated. Please use Device::realize instead.
Quoted 707 lines
hw/net/etsec.c new file +43
-0+ dc->reset = etsec_reset; + dc->props = etsec_properties; +} + +static TypeInfo etsec_info = { + .name ="eTSEC" , + .parent =TYPE_SYS_BUS_DEVICE , + .instance_size =sizeof (eTSEC), + .class_init = etsec_class_init, +}; + +static void etsec_register_types (void ) +{ +type_register_static (&etsec_info); +} + +type_init (etsec_register_types) + +DeviceState *etsec_create(hwaddr base, +MemoryRegion * mr, +NICInfo * nd, +qemu_irq tx_irq, +qemu_irq rx_irq, +qemu_irq err_irq) +{ +DeviceState *dev; + + dev =qdev_create (NULL ,"eTSEC" ); +qdev_set_nic_properties (dev, nd); + +if (qdev_init (dev)) { +return NULL ; + } + +sysbus_connect_irq (SYS_BUS_DEVICE (dev),0 , tx_irq); +sysbus_connect_irq (SYS_BUS_DEVICE (dev),1 , rx_irq); +sysbus_connect_irq (SYS_BUS_DEVICE (dev),2 , err_irq); + +memory_region_add_subregion (mr, base, +SYS_BUS_DEVICE (dev)->mmio[0 ].memory); + +return dev; +}hw/net/etsec.h new file +169
-0@@ -0,0 +1,169 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef _ETSEC_H_ +#define _ETSEC_H_ + +#include "hw/qdev.h" +#include "hw/sysbus.h" +#include "net/net.h" +#include "hw/ptimer.h" + +/* Buffer Descriptors */ + +typedef struct eTSEC_rxtx_bd { +uint16_t flags; +uint16_t length; +uint32_t bufptr; +}eTSEC_rxtx_bd ; + +#define BD_WRAP (1 << 13) +#define BD_INTERRUPT (1 << 12) +#define BD_LAST (1 << 11) + +#define BD_TX_READY (1 << 15) +#define BD_TX_PADCRC (1 << 14) +#define BD_TX_TC (1 << 10) +#define BD_TX_PREDEF (1 << 9) +#define BD_TX_HFELC (1 << 7) +#define BD_TX_CFRL (1 << 6) +#define BD_TX_RC_MASK 0xF +#define BD_TX_RC_OFFSET 0x2 +#define BD_TX_TOEUN (1 << 1) +#define BD_TX_TR (1 << 0) + +#define BD_RX_EMPTY (1 << 15) +#define BD_RX_RO1 (1 << 14) +#define BD_RX_FIRST (1 << 10) +#define BD_RX_MISS (1 << 8) +#define BD_RX_BROADCAST (1 << 7) +#define BD_RX_MULTICAST (1 << 6) +#define BD_RX_LG (1 << 5) +#define BD_RX_NO (1 << 4) +#define BD_RX_SH (1 << 3) +#define BD_RX_CR (1 << 2) +#define BD_RX_OV (1 << 1) +#define BD_RX_TR (1 << 0) + +/* Tx FCB flags */ +#define FCB_TX_VLN (1 << 7) +#define FCB_TX_IP (1 << 6) +#define FCB_TX_IP6 (1 << 5) +#define FCB_TX_TUP (1 << 4) +#define FCB_TX_UDP (1 << 3) +#define FCB_TX_CIP (1 << 2) +#define FCB_TX_CTU (1 << 1) +#define FCB_TX_NPH (1 << 0) + +/* PHY Status Register */ +#define MII_SR_EXTENDED_CAPS 0x0001/* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002/* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004/* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008/* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010/* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020/* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040/* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100/* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200/* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400/* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800/* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000/* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000/* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000/* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000/* 100T4 Capable */ + +/* eTSEC */ + +#define REG_NUMBER 1024 + +typedef struct eTSEC_Register { +const char *name; +const char *desc; +uint32_t access; +uint32_t value; +}eTSEC_Register ; + +typedef struct eTSEC { +SysBusDevice busdev; + +MemoryRegion io_area; + +eTSEC_Register regs[REG_NUMBER ]; + +NICState *nic; +NICConf conf; + +/* Tx */ + +uint8_t *tx_buffer; +uint32_t tx_buffer_len; +eTSEC_rxtx_bd first_bd; + +/* Rx */ + +uint8_t *rx_buffer; +uint32_t rx_buffer_len; +uint32_t rx_remaining_data; +uint8_t rx_first_in_frame; +uint8_t rx_fcb_size; +eTSEC_rxtx_bd rx_first_bd; +uint8_t rx_fcb[10 ]; +uint32_t rx_padding; + +/* IRQs */ +qemu_irq tx_irq; +qemu_irq rx_irq; +qemu_irq err_irq; + + +uint16_t phy_status; +uint16_t phy_control; + +/* Polling */ +QEMUBH *bh; +struct ptimer_state *ptimer; + +}eTSEC ; + +#define eTSEC_TRANSMIT 1 +#define eTSEC_RECEIVE 2 + +DeviceState *etsec_create (hwaddr base, +MemoryRegion *mr, +NICInfo *nd, +qemu_irq tx_irq, +qemu_irq rx_irq, +qemu_irq err_irq); + +void walk_tx_ring (eTSEC *etsec,int ring_nbr); +void walk_rx_ring (eTSEC *etsec,int ring_nbr); +void rx_ring_write (eTSEC *etsec,const uint8_t *buf,size_t size); + +void write_miim (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value); + +void miim_link_status (eTSEC *etsec,NetClientState *nc); + +#endif /* ! _ETSEC_H_ */ hw/net/etsec_miim.c new file +146
-0@@ -0,0 +1,146 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "etsec.h" +#include "etsec_registers.h" + +/* #define DEBUG_MIIM */ + +#define MIIM_CONTROL 0 +#define MIIM_STATUS 1 +#define MIIM_PHY_ID_1 2 +#define MIIM_PHY_ID_2 3 +#define MIIM_T2_STATUS 10 +#define MIIM_EXT_STATUS 15 + +static void miim_read_cycle (eTSEC *etsec) +{ +uint8_t phy; +uint8_t addr; +uint16_t value; + + phy = (etsec->regs[MIIMADD ].value >>8 ) &0x1F ; + (void )phy;/* Unreferenced */ + addr = etsec->regs[MIIMADD ].value &0x1F ; + +switch (addr) { +case MIIM_CONTROL : + value = etsec->phy_control; +break ; +case MIIM_STATUS : + value = etsec->phy_status; +break ; +case MIIM_T2_STATUS : + value =0x1800 ;/* Local and remote receivers OK */ +break ; +default : + value =0x0 ; +break ; + }; + +#ifdef DEBUG_MIIM +printf ("%s phy:%d addr:0x%x value:0x%x\n" , __func__, phy, addr, value); +#endif + + etsec->regs[MIIMSTAT ].value = value; +} + +static void miim_write_cycle (eTSEC *etsec) +{ +uint8_t phy; +uint8_t addr; +uint16_t value; + + phy = (etsec->regs[MIIMADD ].value >>8 ) &0x1F ; + (void )phy;/* Unreferenced */ + addr = etsec->regs[MIIMADD ].value &0x1F ; + value = etsec->regs[MIIMCON ].value &0xffff ; + +#ifdef DEBUG_MIIM +printf ("%s phy:%d addr:0x%x value:0x%x\n" , __func__, phy, addr, value); +#endif + +switch (addr) { +case MIIM_CONTROL : + etsec->phy_control = value & ~(0x8100 ); +break ; +default : +break ; + }; +} + +void write_miim (eTSEC *etsec, +eTSEC_Register *reg, +uint32_t reg_index, +uint32_t value) +{ + +switch (reg_index) { + +case MIIMCOM : +/* Read and scan cycle */ + +if ((!(reg->value &MIIMCOM_READ )) && (value &MIIMCOM_READ )) { +/* Read */ +miim_read_cycle (etsec); + } + reg->value = value; +break ; + +case MIIMCON : + reg->value = value &0xffff ; +miim_write_cycle (etsec); +break ; + +default : +/* Default handling */ +switch (reg->access) { + +case ACC_RW : +case ACC_WO : + reg->value = value; +break ; + +case ACC_w1c: + reg->value &= ~value; +break ; + +case ACC_RO : +default : +/* Read Only or Unknown register */ +break ; + } + } + +} + +void miim_link_status (eTSEC *etsec,NetClientState *nc) +{ +/* Set link status */ +if (nc->link_down) { + etsec->phy_status &= ~MII_SR_LINK_STATUS ; + }else { + etsec->phy_status |=MII_SR_LINK_STATUS ; + } +}hw/net/etsec_registers.c new file +295
-0@@ -0,0 +1,295 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#include "etsec_registers.h" + +const eTSEC_Register_Definition eTSEC_registers_def[] = { +{0x000 ,"TSEC_ID" ,"Controller ID register" ,ACC_RO ,0x01240000 }, +{0x004 ,"TSEC_ID2" ,"Controller ID register 2" ,ACC_RO ,0x003000F0 }, +{0x010 ,"IEVENT" ,"Interrupt event register" , ACC_w1c,0x00000000 }, +{0x014 ,"IMASK" ,"Interrupt mask register" ,ACC_RW ,0x00000000 }, +{0x018 ,"EDIS" ,"Error disabled register" ,ACC_RW ,0x00000000 }, +{0x020 ,"ECNTRL" ,"Ethernet control register" ,ACC_RW ,0x00000040 }, +{0x028 ,"PTV" ,"Pause time value register" ,ACC_RW ,0x00000000 }, +{0x02C ,"DMACTRL" ,"DMA control register" ,ACC_RW ,0x00000000 }, +{0x030 ,"TBIPA" ,"TBI PHY address register" ,ACC_RW ,0x00000000 }, + +/* eTSEC FIFO Control and Status Registers */ + +{0x058 ,"FIFO_RX_ALARM" ,"FIFO receive alarm start threshold register" ,ACC_RW ,0x00000040 }, +{0x05C ,"FIFO_RX_ALARM_SHUTOFF" ,"FIFO receive alarm shut-off threshold register" ,ACC_RW ,0x00000080 }, +{0x08C ,"FIFO_TX_THR" ,"FIFO transmit threshold register" ,ACC_RW ,0x00000080 }, +{0x098 ,"FIFO_TX_STARVE" ,"FIFO transmit starve register" ,ACC_RW ,0x00000040 }, +{0x09C ,"FIFO_TX_STARVE_SHUTOFF" ,"FIFO transmit starve shut-off register" ,ACC_RW ,0x00000080 }, + +/* eTSEC Transmit Control and Status Registers */ + +{0x100 ,"TCTRL" ,"Transmit control register" ,ACC_RW ,0x00000000 }, +{0x104 ,"TSTAT" ,"Transmit status register" , ACC_w1c,0x00000000 }, +{0x108 ,"DFVLAN" ,"Default VLAN control word" ,ACC_RW ,0x81000000 }, +{0x110 ,"TXIC" ,"Transmit interrupt coalescing register" ,ACC_RW ,0x00000000 }, +{0x114 ,"TQUEUE" ,"Transmit queue control register" ,ACC_RW ,0x00008000 }, +{0x140 ,"TR03WT" ,"TxBD Rings 0-3 round-robin weightings" ,ACC_RW ,0x00000000 }, +{0x144 ,"TR47WT" ,"TxBD Rings 4-7 round-robin weightings" ,ACC_RW ,0x00000000 }, +{0x180 ,"TBDBPH" ,"Tx data buffer pointer high bits" ,ACC_RW ,0x00000000 }, +{0x184 ,"TBPTR0" ,"TxBD pointer for ring 0" ,ACC_RW ,0x00000000 }, +{0x18C ,"TBPTR1" ,"TxBD pointer for ring 1" ,ACC_RW ,0x00000000 }, +{0x194 ,"TBPTR2" ,"TxBD pointer for ring 2" ,ACC_RW ,0x00000000 }, +{0x19C ,"TBPTR3" ,"TxBD pointer for ring 3" ,ACC_RW ,0x00000000 }, +{0x1A4 ,"TBPTR4" ,"TxBD pointer for ring 4" ,ACC_RW ,0x00000000 }, +{0x1AC ,"TBPTR5" ,"TxBD pointer for ring 5" ,ACC_RW ,0x00000000 }, +{0x1B4 ,"TBPTR6" ,"TxBD pointer for ring 6" ,ACC_RW ,0x00000000 }, +{0x1BC ,"TBPTR7" ,"TxBD pointer for ring 7" ,ACC_RW ,0x00000000 }, +{0x200 ,"TBASEH" ,"TxBD base address high bits" ,ACC_RW ,0x00000000 }, +{0x204 ,"TBASE0" ,"TxBD base address of ring 0" ,ACC_RW ,0x00000000 }, +{0x20C ,"TBASE1" ,"TxBD base address of ring 1" ,ACC_RW ,0x00000000 }, +{0x214 ,"TBASE2" ,"TxBD base address of ring 2" ,ACC_RW ,0x00000000 }, +{0x21C ,"TBASE3" ,"TxBD base address of ring 3" ,ACC_RW ,0x00000000 }, +{0x224 ,"TBASE4" ,"TxBD base address of ring 4" ,ACC_RW ,0x00000000 }, +{0x22C ,"TBASE5" ,"TxBD base address of ring 5" ,ACC_RW ,0x00000000 }, +{0x234 ,"TBASE6" ,"TxBD base address of ring 6" ,ACC_RW ,0x00000000 }, +{0x23C ,"TBASE7" ,"TxBD base address of ring 7" ,ACC_RW ,0x00000000 }, +{0x280 ,"TMR_TXTS1_ID" ,"Tx time stamp identification tag (set 1)" ,ACC_RO ,0x00000000 }, +{0x284 ,"TMR_TXTS2_ID" ,"Tx time stamp identification tag (set 2)" ,ACC_RO ,0x00000000 }, +{0x2C0 ,"TMR_TXTS1_H" ,"Tx time stamp high (set 1)" ,ACC_RO ,0x00000000 }, +{0x2C4 ,"TMR_TXTS1_L" ,"Tx time stamp high (set 1)" ,ACC_RO ,0x00000000 }, +{0x2C8 ,"TMR_TXTS2_H" ,"Tx time stamp high (set 2)" ,ACC_RO ,0x00000000 }, +{0x2CC ,"TMR_TXTS2_L" ,"Tx time stamp high (set 2)" ,ACC_RO ,0x00000000 }, + +/* eTSEC Receive Control and Status Registers */ + +{0x300 ,"RCTRL" ,"Receive control register" ,ACC_RW ,0x00000000 }, +{0x304 ,"RSTAT" ,"Receive status register" , ACC_w1c,0x00000000 }, +{0x310 ,"RXIC" ,"Receive interrupt coalescing register" ,ACC_RW ,0x00000000 }, +{0x314 ,"RQUEUE" ,"Receive queue control register." ,ACC_RW ,0x00800080 }, +{0x330 ,"RBIFX" ,"Receive bit field extract control register" ,ACC_RW ,0x00000000 }, +{0x334 ,"RQFAR" ,"Receive queue filing table address register" ,ACC_RW ,0x00000000 }, +{0x338 ,"RQFCR" ,"Receive queue filing table control register" ,ACC_RW ,0x00000000 }, +{0x33C ,"RQFPR" ,"Receive queue filing table property register" ,ACC_RW ,0x00000000 }, +{0x340 ,"MRBLR" ,"Maximum receive buffer length register" ,ACC_RW ,0x00000000 }, +{0x380 ,"RBDBPH" ,"Rx data buffer pointer high bits" ,ACC_RW ,0x00000000 }, +{0x384 ,"RBPTR0" ,"RxBD pointer for ring 0" ,ACC_RW ,0x00000000 }, +{0x38C ,"RBPTR1" ,"RxBD pointer for ring 1" ,ACC_RW ,0x00000000 }, +{0x394 ,"RBPTR2" ,"RxBD pointer for ring 2" ,ACC_RW ,0x00000000 }, +{0x39C ,"RBPTR3" ,"RxBD pointer for ring 3" ,ACC_RW ,0x00000000 }, +{0x3A4 ,"RBPTR4" ,"RxBD pointer for ring 4" ,ACC_RW ,0x00000000 }, +{0x3AC ,"RBPTR5" ,"RxBD pointer for ring 5" ,ACC_RW ,0x00000000 }, +{0x3B4 ,"RBPTR6" ,"RxBD pointer for ring 6" ,ACC_RW ,0x00000000 }, +{0x3BC ,"RBPTR7" ,"RxBD pointer for ring 7" ,ACC_RW ,0x00000000 }, +{0x400 ,"RBASEH" ,"RxBD base address high bits" ,ACC_RW ,0x00000000 }, +{0x404 ,"RBASE0" ,"RxBD base address of ring 0" ,ACC_RW ,0x00000000 }, +{0x40C ,"RBASE1" ,"RxBD base address of ring 1" ,ACC_RW ,0x00000000 }, +{0x414 ,"RBASE2" ,"RxBD base address of ring 2" ,ACC_RW ,0x00000000 }, +{0x41C ,"RBASE3" ,"RxBD base address of ring 3" ,ACC_RW ,0x00000000 }, +{0x424 ,"RBASE4" ,"RxBD base address of ring 4" ,ACC_RW ,0x00000000 }, +{0x42C ,"RBASE5" ,"RxBD base address of ring 5" ,ACC_RW ,0x00000000 }, +{0x434 ,"RBASE6" ,"RxBD base address of ring 6" ,ACC_RW ,0x00000000 }, +{0x43C ,"RBASE7" ,"RxBD base address of ring 7" ,ACC_RW ,0x00000000 }, +{0x4C0 ,"TMR_RXTS_H" ,"Rx timer time stamp register high" ,ACC_RW ,0x00000000 }, +{0x4C4 ,"TMR_RXTS_L" ,"Rx timer time stamp register low" ,ACC_RW ,0x00000000 }, + +/* eTSEC MAC Registers */ + +{0x500 ,"MACCFG1" ,"MAC configuration register 1" ,ACC_RW ,0x00000000 }, +{0x504 ,"MACCFG2" ,"MAC configuration register 2" ,ACC_RW ,0x00007000 }, +{0x508 ,"IPGIFG" ,"Inter-packet/inter-frame gap register" ,ACC_RW ,0x40605060 }, +{0x50C ,"HAFDUP" ,"Half-duplex control" ,ACC_RW ,0x00A1F037 }, +{0x510 ,"MAXFRM" ,"Maximum frame length" ,ACC_RW ,0x00000600 }, +{0x520 ,"MIIMCFG" ,"MII management configuration" ,ACC_RW ,0x00000007 }, +{0x524 ,"MIIMCOM" ,"MII management command" ,ACC_RW ,0x00000000 }, +{0x528 ,"MIIMADD" ,"MII management address" ,ACC_RW ,0x00000000 }, +{0x52C ,"MIIMCON" ,"MII management control" ,ACC_WO ,0x00000000 }, +{0x530 ,"MIIMSTAT" ,"MII management status" ,ACC_RO ,0x00000000 }, +{0x534 ,"MIIMIND" ,"MII management indicator" ,ACC_RO ,0x00000000 }, +{0x53C ,"IFSTAT" ,"Interface status" ,ACC_RO ,0x00000000 }, +{0x540 ,"MACSTNADDR1" ,"MAC station address register 1" ,ACC_RW ,0x00000000 }, +{0x544 ,"MACSTNADDR2" ,"MAC station address register 2" ,ACC_RW ,0x00000000 }, +{0x548 ,"MAC01ADDR1" ,"MAC exact match address 1, part 1" ,ACC_RW ,0x00000000 }, +{0x54C ,"MAC01ADDR2" ,"MAC exact match address 1, part 2" ,ACC_RW ,0x00000000 }, +{0x550 ,"MAC02ADDR1" ,"MAC exact match address 2, part 1" ,ACC_RW ,0x00000000 }, +{0x554 ,"MAC02ADDR2" ,"MAC exact match address 2, part 2" ,ACC_RW ,0x00000000 }, +{0x558 ,"MAC03ADDR1" ,"MAC exact match address 3, part 1" ,ACC_RW ,0x00000000 }, +{0x55C ,"MAC03ADDR2" ,"MAC exact match address 3, part 2" ,ACC_RW ,0x00000000 }, +{0x560 ,"MAC04ADDR1" ,"MAC exact match address 4, part 1" ,ACC_RW ,0x00000000 }, +{0x564 ,"MAC04ADDR2" ,"MAC exact match address 4, part 2" ,ACC_RW ,0x00000000 }, +{0x568 ,"MAC05ADDR1" ,"MAC exact match address 5, part 1" ,ACC_RW ,0x00000000 }, +{0x56C ,"MAC05ADDR2" ,"MAC exact match address 5, part 2" ,ACC_RW ,0x00000000 }, +{0x570 ,"MAC06ADDR1" ,"MAC exact match address 6, part 1" ,ACC_RW ,0x00000000 }, +{0x574 ,"MAC06ADDR2" ,"MAC exact match address 6, part 2" ,ACC_RW ,0x00000000 }, +{0x578 ,"MAC07ADDR1" ,"MAC exact match address 7, part 1" ,ACC_RW ,0x00000000 }, +{0x57C ,"MAC07ADDR2" ,"MAC exact match address 7, part 2" ,ACC_RW ,0x00000000 }, +{0x580 ,"MAC08ADDR1" ,"MAC exact match address 8, part 1" ,ACC_RW ,0x00000000 }, +{0x584 ,"MAC08ADDR2" ,"MAC exact match address 8, part 2" ,ACC_RW ,0x00000000 }, +{0x588 ,"MAC09ADDR1" ,"MAC exact match address 9, part 1" ,ACC_RW ,0x00000000 }, +{0x58C ,"MAC09ADDR2" ,"MAC exact match address 9, part 2" ,ACC_RW ,0x00000000 }, +{0x590 ,"MAC10ADDR1" ,"MAC exact match address 10, part 1" ,ACC_RW ,0x00000000 }, +{0x594 ,"MAC10ADDR2" ,"MAC exact match address 10, part 2" ,ACC_RW ,0x00000000 }, +{0x598 ,"MAC11ADDR1" ,"MAC exact match address 11, part 1" ,ACC_RW ,0x00000000 }, +{0x59C ,"MAC11ADDR2" ,"MAC exact match address 11, part 2" ,ACC_RW ,0x00000000 }, +{0x5A0 ,"MAC12ADDR1" ,"MAC exact match address 12, part 1" ,ACC_RW ,0x00000000 }, +{0x5A4 ,"MAC12ADDR2" ,"MAC exact match address 12, part 2" ,ACC_RW ,0x00000000 }, +{0x5A8 ,"MAC13ADDR1" ,"MAC exact match address 13, part 1" ,ACC_RW ,0x00000000 }, +{0x5AC ,"MAC13ADDR2" ,"MAC exact match address 13, part 2" ,ACC_RW ,0x00000000 }, +{0x5B0 ,"MAC14ADDR1" ,"MAC exact match address 14, part 1" ,ACC_RW ,0x00000000 }, +{0x5B4 ,"MAC14ADDR2" ,"MAC exact match address 14, part 2" ,ACC_RW ,0x00000000 }, +{0x5B8 ,"MAC15ADDR1" ,"MAC exact match address 15, part 1" ,ACC_RW ,0x00000000 }, +{0x5BC ,"MAC15ADDR2" ,"MAC exact match address 15, part 2" ,ACC_RW ,0x00000000 }, + +/* eTSEC, "Transmit", "and", Receive, Counters */ + +{0x680 ,"TR64" ,"Transmit and receive 64-byte frame counter " ,ACC_RW ,0x00000000 }, +{0x684 ,"TR127" ,"Transmit and receive 65- to 127-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x688 ,"TR255" ,"Transmit and receive 128- to 255-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x68C ,"TR511" ,"Transmit and receive 256- to 511-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x690 ,"TR1K" ,"Transmit and receive 512- to 1023-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x694 ,"TRMAX" ,"Transmit and receive 1024- to 1518-byte frame counter" ,ACC_RW ,0x00000000 }, +{0x698 ,"TRMGV" ,"Transmit and receive 1519- to 1522-byte good VLAN frame count" ,ACC_RW ,0x00000000 }, + +/* eTSEC Receive Counters */ + +{0x69C ,"RBYT" ,"Receive byte counter" ,ACC_RW ,0x00000000 }, +{0x6A0 ,"RPKT" ,"Receive packet counter" ,ACC_RW ,0x00000000 }, +{0x6A4 ,"RFCS" ,"Receive FCS error counter" ,ACC_RW ,0x00000000 }, +{0x6A8 ,"RMCA" ,"Receive multicast packet counter" ,ACC_RW ,0x00000000 }, +{0x6AC ,"RBCA" ,"Receive broadcast packet counter" ,ACC_RW ,0x00000000 }, +{0x6B0 ,"RXCF" ,"Receive control frame packet counter " ,ACC_RW ,0x00000000 }, +{0x6B4 ,"RXPF" ,"Receive PAUSE frame packet counter" ,ACC_RW ,0x00000000 }, +{0x6B8 ,"RXUO" ,"Receive unknown OP code counter " ,ACC_RW ,0x00000000 }, +{0x6BC ,"RALN" ,"Receive alignment error counter " ,ACC_RW ,0x00000000 }, +{0x6C0 ,"RFLR" ,"Receive frame length error counter " ,ACC_RW ,0x00000000 }, +{0x6C4 ,"RCDE" ,"Receive code error counter " ,ACC_RW ,0x00000000 }, +{0x6C8 ,"RCSE" ,"Receive carrier sense error counter" ,ACC_RW ,0x00000000 }, +{0x6CC ,"RUND" ,"Receive undersize packet counter" ,ACC_RW ,0x00000000 }, +{0x6D0 ,"ROVR" ,"Receive oversize packet counter " ,ACC_RW ,0x00000000 }, +{0x6D4 ,"RFRG" ,"Receive fragments counter" ,ACC_RW ,0x00000000 }, +{0x6D8 ,"RJBR" ,"Receive jabber counter " ,ACC_RW ,0x00000000 }, +{0x6DC ,"RDRP" ,"Receive drop counter" ,ACC_RW ,0x00000000 }, + +/* eTSEC Transmit Counters */ + +{0x6E0 ,"TBYT" ,"Transmit byte counter" ,ACC_RW ,0x00000000 }, +{0x6E4 ,"TPKT" ,"Transmit packet counter" ,ACC_RW ,0x00000000 }, +{0x6E8 ,"TMCA" ,"Transmit multicast packet counter " ,ACC_RW ,0x00000000 }, +{0x6EC ,"TBCA" ,"Transmit broadcast packet counter " ,ACC_RW ,0x00000000 }, +{0x6F0 ,"TXPF" ,"Transmit PAUSE control frame counter " ,ACC_RW ,0x00000000 }, +{0x6F4 ,"TDFR" ,"Transmit deferral packet counter " ,ACC_RW ,0x00000000 }, +{0x6F8 ,"TEDF" ,"Transmit excessive deferral packet counter " ,ACC_RW ,0x00000000 }, +{0x6FC ,"TSCL" ,"Transmit single collision packet counter" ,ACC_RW ,0x00000000 }, +{0x700 ,"TMCL" ,"Transmit multiple collision packet counter" ,ACC_RW ,0x00000000 }, +{0x704 ,"TLCL" ,"Transmit late collision packet counter" ,ACC_RW ,0x00000000 }, +{0x708 ,"TXCL" ,"Transmit excessive collision packet counter" ,ACC_RW ,0x00000000 }, +{0x70C ,"TNCL" ,"Transmit total collision counter " ,ACC_RW ,0x00000000 }, +{0x714 ,"TDRP" ,"Transmit drop frame counter" ,ACC_RW ,0x00000000 }, +{0x718 ,"TJBR" ,"Transmit jabber frame counter " ,ACC_RW ,0x00000000 }, +{0x71C ,"TFCS" ,"Transmit FCS error counter" ,ACC_RW ,0x00000000 }, +{0x720 ,"TXCF" ,"Transmit control frame counter " ,ACC_RW ,0x00000000 }, +{0x724 ,"TOVR" ,"Transmit oversize frame counter" ,ACC_RW ,0x00000000 }, +{0x728 ,"TUND" ,"Transmit undersize frame counter " ,ACC_RW ,0x00000000 }, +{0x72C ,"TFRG" ,"Transmit fragments frame counter " ,ACC_RW ,0x00000000 }, + +/* eTSEC Counter Control and TOE Statistics Registers */ + +{0x730 ,"CAR1" ,"Carry register one register" , ACC_w1c,0x00000000 }, +{0x734 ,"CAR2" ,"Carry register two register " , ACC_w1c,0x00000000 }, +{0x738 ,"CAM1" ,"Carry register one mask register " ,ACC_RW ,0xFE03FFFF }, +{0x73C ,"CAM2" ,"Carry register two mask register " ,ACC_RW ,0x000FFFFD }, +{0x740 ,"RREJ" ,"Receive filer rejected packet counter" ,ACC_RW ,0x00000000 }, + +/* Hash Function Registers */ + +{0x800 ,"IGADDR0" ,"Individual/group address register 0" ,ACC_RW ,0x00000000 }, +{0x804 ,"IGADDR1" ,"Individual/group address register 1" ,ACC_RW ,0x00000000 }, +{0x808 ,"IGADDR2" ,"Individual/group address register 2" ,ACC_RW ,0x00000000 }, +{0x80C ,"IGADDR3" ,"Individual/group address register 3" ,ACC_RW ,0x00000000 }, +{0x810 ,"IGADDR4" ,"Individual/group address register 4" ,ACC_RW ,0x00000000 }, +{0x814 ,"IGADDR5" ,"Individual/group address register 5" ,ACC_RW ,0x00000000 }, +{0x818 ,"IGADDR6" ,"Individual/group address register 6" ,ACC_RW ,0x00000000 }, +{0x81C ,"IGADDR7" ,"Individual/group address register 7" ,ACC_RW ,0x00000000 }, +{0x880 ,"GADDR0" ,"Group address register 0" ,ACC_RW ,0x00000000 }, +{0x884 ,"GADDR1" ,"Group address register 1" ,ACC_RW ,0x00000000 }, +{0x888 ,"GADDR2" ,"Group address register 2" ,ACC_RW ,0x00000000 }, +{0x88C ,"GADDR3" ,"Group address register 3" ,ACC_RW ,0x00000000 }, +{0x890 ,"GADDR4" ,"Group address register 4" ,ACC_RW ,0x00000000 }, +{0x894 ,"GADDR5" ,"Group address register 5" ,ACC_RW ,0x00000000 }, +{0x898 ,"GADDR6" ,"Group address register 6" ,ACC_RW ,0x00000000 }, +{0x89C ,"GADDR7" ,"Group address register 7" ,ACC_RW ,0x00000000 }, + +/* eTSEC DMA Attribute Registers */ + +{0xBF8 ,"ATTR" ,"Attribute register" ,ACC_RW ,0x00000000 }, +{0xBFC ,"ATTRELI" ,"Attribute extract length and extract index register" ,ACC_RW ,0x00000000 }, + + +/* eTSEC Lossless Flow Control Registers */ + +{0xC00 ,"RQPRM0" ,"Receive Queue Parameters register 0 " ,ACC_RW ,0x00000000 }, +{0xC04 ,"RQPRM1" ,"Receive Queue Parameters register 1 " ,ACC_RW ,0x00000000 }, +{0xC08 ,"RQPRM2" ,"Receive Queue Parameters register 2 " ,ACC_RW ,0x00000000 }, +{0xC0C ,"RQPRM3" ,"Receive Queue Parameters register 3 " ,ACC_RW ,0x00000000 }, +{0xC10 ,"RQPRM4" ,"Receive Queue Parameters register 4 " ,ACC_RW ,0x00000000 }, +{0xC14 ,"RQPRM5" ,"Receive Queue Parameters register 5 " ,ACC_RW ,0x00000000 }, +{0xC18 ,"RQPRM6" ,"Receive Queue Parameters register 6 " ,ACC_RW ,0x00000000 }, +{0xC1C ,"RQPRM7" ,"Receive Queue Parameters register 7 " ,ACC_RW ,0x00000000 }, +{0xC44 ,"RFBPTR0" ,"Last Free RxBD pointer for ring 0" ,ACC_RW ,0x00000000 }, +{0xC4C ,"RFBPTR1" ,"Last Free RxBD pointer for ring 1" ,ACC_RW ,0x00000000 }, +{0xC54 ,"RFBPTR2" ,"Last Free RxBD pointer for ring 2" ,ACC_RW ,0x00000000 }, +{0xC5C ,"RFBPTR3" ,"Last Free RxBD pointer for ring 3" ,ACC_RW ,0x00000000 }, +{0xC64 ,"RFBPTR4" ,"Last Free RxBD pointer for ring 4" ,ACC_RW ,0x00000000 }, +{0xC6C ,"RFBPTR5" ,"Last Free RxBD pointer for ring 5" ,ACC_RW ,0x00000000 }, +{0xC74 ,"RFBPTR6" ,"Last Free RxBD pointer for ring 6" ,ACC_RW ,0x00000000 }, +{0xC7C ,"RFBPTR7" ,"Last Free RxBD pointer for ring 7" ,ACC_RW ,0x00000000 }, + +/* eTSEC Future Expansion Space */ + +/* Reserved*/ + +/* eTSEC IEEE 1588 Registers */ + +{0xE00 ,"TMR_CTRL" ,"Timer control register" ,ACC_RW ,0x00010001 }, +{0xE04 ,"TMR_TEVENT" ,"time stamp event register" , ACC_w1c,0x00000000 }, +{0xE08 ,"TMR_TEMASK" ,"Timer event mask register" ,ACC_RW ,0x00000000 }, +{0xE0C ,"TMR_PEVENT" ,"time stamp event register" ,ACC_RW ,0x00000000 }, +{0xE10 ,"TMR_PEMASK" ,"Timer event mask register" ,ACC_RW ,0x00000000 }, +{0xE14 ,"TMR_STAT" ,"time stamp status register" ,ACC_RW ,0x00000000 }, +{0xE18 ,"TMR_CNT_H" ,"timer counter high register" ,ACC_RW ,0x00000000 }, +{0xE1C ,"TMR_CNT_L" ,"timer counter low register" ,ACC_RW ,0x00000000 }, +{0xE20 ,"TMR_ADD" ,"Timer drift compensation addend register" ,ACC_RW ,0x00000000 }, +{0xE24 ,"TMR_ACC" ,"Timer accumulator register" ,ACC_RW ,0x00000000 }, +{0xE28 ,"TMR_PRSC" ,"Timer prescale" ,ACC_RW ,0x00000002 }, +{0xE30 ,"TMROFF_H" ,"Timer offset high" ,ACC_RW ,0x00000000 }, +{0xE34 ,"TMROFF_L" ,"Timer offset low" ,ACC_RW ,0x00000000 }, +{0xE40 ,"TMR_ALARM1_H" ,"Timer alarm 1 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE44 ,"TMR_ALARM1_L" ,"Timer alarm 1 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE48 ,"TMR_ALARM2_H" ,"Timer alarm 2 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE4C ,"TMR_ALARM2_L" ,"Timer alarm 2 high register" ,ACC_RW ,0xFFFFFFFF }, +{0xE80 ,"TMR_FIPER1" ,"Timer fixed period interval" ,ACC_RW ,0xFFFFFFFF }, +{0xE84 ,"TMR_FIPER2" ,"Timer fixed period interval" ,ACC_RW ,0xFFFFFFFF }, +{0xE88 ,"TMR_FIPER3" ,"Timer fixed period interval" ,ACC_RW ,0xFFFFFFFF }, +{0xEA0 ,"TMR_ETTS1_H" ,"Time stamp of general purpose external trigger " ,ACC_RW ,0x00000000 }, +{0xEA4 ,"TMR_ETTS1_L" ,"Time stamp of general purpose external trigger" ,ACC_RW ,0x00000000 }, +{0xEA8 ,"TMR_ETTS2_H" ,"Time stamp of general purpose external trigger " ,ACC_RW ,0x00000000 }, +{0xEAC ,"TMR_ETTS2_L" ,"Time stamp of general purpose external trigger" ,ACC_RW ,0x00000000 }, + +/* End Of Table */ +{0x0 ,0x0 ,0x0 ,0x0 ,0x0 } +};hw/net/etsec_registers.h new file +30
-0@@ -0,0 +1,302 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef _ETSEC_REGISTERS_H_ +#define _ETSEC_REGISTERS_H_ + +#include <stdint.h> + +typedef struct eTSEC_Register_Definition { + uint32_t offset;
hw/net/etsec_registers.h line 40
Quoted 10 lines
hw/net/etsec_registers.h new file +10
-0+const char *name; +const char *desc; +uint32_t access; +uint32_t reset; +} eTSEC_Register_Definition; + +#define ACC_RW 1/* Read/Write */ +#define ACC_RO 2/* Read Only */ +#define ACC_WO 3/* Write Only */ +#define ACC_w1c 4/* Write 1 to clear */
ACC_W1C. Would it be cleaner with an enum instead?
Quoted 364 lines
hw/net/etsec_registers.h new file +262
-0+#define ACC_UNKNOWN 4/* Unknown register*/ + +extern const eTSEC_Register_Definition eTSEC_registers_def[]; + +#define DMACTRL_LE (1 << 15) +#define DMACTRL_GRS (1 << 4) +#define DMACTRL_GTS (1 << 3) +#define DMACTRL_WOP (1 << 0) + +#define IEVENT_RXF (1 << 7) +#define IEVENT_GRSC (1 << 8) +#define IEVENT_RXB (1 << 15) +#define IEVENT_TXF (1 << 20) +#define IEVENT_TXB (1 << 21) +#define IEVENT_TXC (1 << 23) +#define IEVENT_GTSC (1 << 25) +#define IEVENT_BSY (1 << 29) +#define IEVENT_RXC (1 << 30) + +#define IMASK_RXFEN (1 << 7) +#define IMASK_GRSCEN (1 << 8) +#define IMASK_RXBEN (1 << 15) +#define IMASK_TXFEN (1 << 20) +#define IMASK_TXBEN (1 << 21) +#define IMASK_GTSCEN (1 << 25) + +#define MACCFG1_TX_EN (1 << 0) +#define MACCFG1_RX_EN (1 << 2) + +#define MACCFG2_CRC_EN (1 << 1) +#define MACCFG2_PADCRC (1 << 2) + +#define MIIMCOM_READ (1 << 0) +#define MIIMCOM_SCAN (1 << 1) + +#define RCTRL_PRSDEP_MASK (0x3) +#define RCTRL_PRSDEP_OFFSET (6) +#define RCTRL_RSF (1 << 2) + +/* Index of each register */ + +#define TSEC_ID (0x000 / 4) +#define TSEC_ID2 (0x004 / 4) +#define IEVENT (0x010 / 4) +#define IMASK (0x014 / 4) +#define EDIS (0x018 / 4) +#define ECNTRL (0x020 / 4) +#define PTV (0x028 / 4) +#define DMACTRL (0x02C / 4) +#define TBIPA (0x030 / 4) +#define TCTRL (0x100 / 4) +#define TSTAT (0x104 / 4) +#define DFVLAN (0x108 / 4) +#define TXIC (0x110 / 4) +#define TQUEUE (0x114 / 4) +#define TR03WT (0x140 / 4) +#define TR47WT (0x144 / 4) +#define TBDBPH (0x180 / 4) +#define TBPTR0 (0x184 / 4) +#define TBPTR1 (0x18C / 4) +#define TBPTR2 (0x194 / 4) +#define TBPTR3 (0x19C / 4) +#define TBPTR4 (0x1A4 / 4) +#define TBPTR5 (0x1AC / 4) +#define TBPTR6 (0x1B4 / 4) +#define TBPTR7 (0x1BC / 4) +#define TBASEH (0x200 / 4) +#define TBASE0 (0x204 / 4) +#define TBASE1 (0x20C / 4) +#define TBASE2 (0x214 / 4) +#define TBASE3 (0x21C / 4) +#define TBASE4 (0x224 / 4) +#define TBASE5 (0x22C / 4) +#define TBASE6 (0x234 / 4) +#define TBASE7 (0x23C / 4) +#define TMR_TXTS1_ID (0x280 / 4) +#define TMR_TXTS2_ID (0x284 / 4) +#define TMR_TXTS1_H (0x2C0 / 4) +#define TMR_TXTS1_L (0x2C4 / 4) +#define TMR_TXTS2_H (0x2C8 / 4) +#define TMR_TXTS2_L (0x2CC / 4) +#define RCTRL (0x300 / 4) +#define RSTAT (0x304 / 4) +#define RXIC (0x310 / 4) +#define RQUEUE (0x314 / 4) +#define RBIFX (0x330 / 4) +#define RQFAR (0x334 / 4) +#define RQFCR (0x338 / 4) +#define RQFPR (0x33C / 4) +#define MRBLR (0x340 / 4) +#define RBDBPH (0x380 / 4) +#define RBPTR0 (0x384 / 4) +#define RBPTR1 (0x38C / 4) +#define RBPTR2 (0x394 / 4) +#define RBPTR3 (0x39C / 4) +#define RBPTR4 (0x3A4 / 4) +#define RBPTR5 (0x3AC / 4) +#define RBPTR6 (0x3B4 / 4) +#define RBPTR7 (0x3BC / 4) +#define RBASEH (0x400 / 4) +#define RBASE0 (0x404 / 4) +#define RBASE1 (0x40C / 4) +#define RBASE2 (0x414 / 4) +#define RBASE3 (0x41C / 4) +#define RBASE4 (0x424 / 4) +#define RBASE5 (0x42C / 4) +#define RBASE6 (0x434 / 4) +#define RBASE7 (0x43C / 4) +#define TMR_RXTS_H (0x4C0 / 4) +#define TMR_RXTS_L (0x4C4 / 4) +#define MACCFG1 (0x500 / 4) +#define MACCFG2 (0x504 / 4) +#define IPGIFG (0x508 / 4) +#define HAFDUP (0x50C / 4) +#define MAXFRM (0x510 / 4) +#define MIIMCFG (0x520 / 4) +#define MIIMCOM (0x524 / 4) +#define MIIMADD (0x528 / 4) +#define MIIMCON (0x52C / 4) +#define MIIMSTAT (0x530 / 4) +#define MIIMIND (0x534 / 4) +#define IFSTAT (0x53C / 4) +#define MACSTNADDR1 (0x540 / 4) +#define MACSTNADDR2 (0x544 / 4) +#define MAC01ADDR1 (0x548 / 4) +#define MAC01ADDR2 (0x54C / 4) +#define MAC02ADDR1 (0x550 / 4) +#define MAC02ADDR2 (0x554 / 4) +#define MAC03ADDR1 (0x558 / 4) +#define MAC03ADDR2 (0x55C / 4) +#define MAC04ADDR1 (0x560 / 4) +#define MAC04ADDR2 (0x564 / 4) +#define MAC05ADDR1 (0x568 / 4) +#define MAC05ADDR2 (0x56C / 4) +#define MAC06ADDR1 (0x570 / 4) +#define MAC06ADDR2 (0x574 / 4) +#define MAC07ADDR1 (0x578 / 4) +#define MAC07ADDR2 (0x57C / 4) +#define MAC08ADDR1 (0x580 / 4) +#define MAC08ADDR2 (0x584 / 4) +#define MAC09ADDR1 (0x588 / 4) +#define MAC09ADDR2 (0x58C / 4) +#define MAC10ADDR1 (0x590 / 4) +#define MAC10ADDR2 (0x594 / 4) +#define MAC11ADDR1 (0x598 / 4) +#define MAC11ADDR2 (0x59C / 4) +#define MAC12ADDR1 (0x5A0 / 4) +#define MAC12ADDR2 (0x5A4 / 4) +#define MAC13ADDR1 (0x5A8 / 4) +#define MAC13ADDR2 (0x5AC / 4) +#define MAC14ADDR1 (0x5B0 / 4) +#define MAC14ADDR2 (0x5B4 / 4) +#define MAC15ADDR1 (0x5B8 / 4) +#define MAC15ADDR2 (0x5BC / 4) +#define TR64 (0x680 / 4) +#define TR127 (0x684 / 4) +#define TR255 (0x688 / 4) +#define TR511 (0x68C / 4) +#define TR1K (0x690 / 4) +#define TRMAX (0x694 / 4) +#define TRMGV (0x698 / 4) +#define RBYT (0x69C / 4) +#define RPKT (0x6A0 / 4) +#define RFCS (0x6A4 / 4) +#define RMCA (0x6A8 / 4) +#define RBCA (0x6AC / 4) +#define RXCF (0x6B0 / 4) +#define RXPF (0x6B4 / 4) +#define RXUO (0x6B8 / 4) +#define RALN (0x6BC / 4) +#define RFLR (0x6C0 / 4) +#define RCDE (0x6C4 / 4) +#define RCSE (0x6C8 / 4) +#define RUND (0x6CC / 4) +#define ROVR (0x6D0 / 4) +#define RFRG (0x6D4 / 4) +#define RJBR (0x6D8 / 4) +#define RDRP (0x6DC / 4) +#define TBYT (0x6E0 / 4) +#define TPKT (0x6E4 / 4) +#define TMCA (0x6E8 / 4) +#define TBCA (0x6EC / 4) +#define TXPF (0x6F0 / 4) +#define TDFR (0x6F4 / 4) +#define TEDF (0x6F8 / 4) +#define TSCL (0x6FC / 4) +#define TMCL (0x700 / 4) +#define TLCL (0x704 / 4) +#define TXCL (0x708 / 4) +#define TNCL (0x70C / 4) +#define TDRP (0x714 / 4) +#define TJBR (0x718 / 4) +#define TFCS (0x71C / 4) +#define TXCF (0x720 / 4) +#define TOVR (0x724 / 4) +#define TUND (0x728 / 4) +#define TFRG (0x72C / 4) +#define CAR1 (0x730 / 4) +#define CAR2 (0x734 / 4) +#define CAM1 (0x738 / 4) +#define CAM2 (0x73C / 4) +#define RREJ (0x740 / 4) +#define IGADDR0 (0x800 / 4) +#define IGADDR1 (0x804 / 4) +#define IGADDR2 (0x808 / 4) +#define IGADDR3 (0x80C / 4) +#define IGADDR4 (0x810 / 4) +#define IGADDR5 (0x814 / 4) +#define IGADDR6 (0x818 / 4) +#define IGADDR7 (0x81C / 4) +#define GADDR0 (0x880 / 4) +#define GADDR1 (0x884 / 4) +#define GADDR2 (0x888 / 4) +#define GADDR3 (0x88C / 4) +#define GADDR4 (0x890 / 4) +#define GADDR5 (0x894 / 4) +#define GADDR6 (0x898 / 4) +#define GADDR7 (0x89C / 4) +#define ATTR (0xBF8 / 4) +#define ATTRELI (0xBFC / 4) +#define RQPRM0 (0xC00 / 4) +#define RQPRM1 (0xC04 / 4) +#define RQPRM2 (0xC08 / 4) +#define RQPRM3 (0xC0C / 4) +#define RQPRM4 (0xC10 / 4) +#define RQPRM5 (0xC14 / 4) +#define RQPRM6 (0xC18 / 4) +#define RQPRM7 (0xC1C / 4) +#define RFBPTR0 (0xC44 / 4) +#define RFBPTR1 (0xC4C / 4) +#define RFBPTR2 (0xC54 / 4) +#define RFBPTR3 (0xC5C / 4) +#define RFBPTR4 (0xC64 / 4) +#define RFBPTR5 (0xC6C / 4) +#define RFBPTR6 (0xC74 / 4) +#define RFBPTR7 (0xC7C / 4) +#define TMR_CTRL (0xE00 / 4) +#define TMR_TEVENT (0xE04 / 4) +#define TMR_TEMASK (0xE08 / 4) +#define TMR_PEVENT (0xE0C / 4) +#define TMR_PEMASK (0xE10 / 4) +#define TMR_STAT (0xE14 / 4) +#define TMR_CNT_H (0xE18 / 4) +#define TMR_CNT_L (0xE1C / 4) +#define TMR_ADD (0xE20 / 4) +#define TMR_ACC (0xE24 / 4) +#define TMR_PRSC (0xE28 / 4) +#define TMROFF_H (0xE30 / 4) +#define TMROFF_L (0xE34 / 4) +#define TMR_ALARM1_H (0xE40 / 4) +#define TMR_ALARM1_L (0xE44 / 4) +#define TMR_ALARM2_H (0xE48 / 4) +#define TMR_ALARM2_L (0xE4C / 4) +#define TMR_FIPER1 (0xE80 / 4) +#define TMR_FIPER2 (0xE84 / 4) +#define TMR_FIPER3 (0xE88 / 4) +#define TMR_ETTS1_H (0xEA0 / 4) +#define TMR_ETTS1_L (0xEA4 / 4) +#define TMR_ETTS2_H (0xEA8 / 4) +#define TMR_ETTS2_L (0xEAC / 4) + +#endif /* ! _ETSEC_REGISTERS_H_ */ hw/net/etsec_rings.c new file +96
-0@@ -0,0 +1,673 @@ +/* +* QEMU Freescale eTSEC Emulator +* +* Copyright (c) 2011-2013 AdaCore +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#include "qemu/bswap.h" +#include "net/checksum.h" + +#include "etsec.h" +#include "etsec_registers.h" + +/* #define ETSEC_RING_DEBUG */ +/* #define HEX_DUMP */ +/* #define DEBUG_BD */ + +#ifdef ETSEC_RING_DEBUG +#define RING_DEBUG (fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__) +#else +#define RING_DEBUG (...) +#endif /* ETSEC_RING_DEBUG */ + +#define RING_DEBUG_A (fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__) + +#ifdef DEBUG_BD + +static void print_tx_bd_flags (uint16_t flags) +{ +printf (" Ready: %d\n" , !!(flags &BD_TX_READY )); +printf (" PAD/CRC: %d\n" , !!(flags &BD_TX_PADCRC )); +printf (" Wrap: %d\n" , !!(flags &BD_WRAP )); +printf (" Interrupt: %d\n" , !!(flags &BD_INTERRUPT )); +printf (" Last in frame: %d\n" , !!(flags &BD_LAST )); +printf (" Tx CRC: %d\n" , !!(flags &BD_TX_TC )); +printf (" User-defined preamble / defer: %d\n" , + !!(flags &BD_TX_PREDEF )); +printf (" Huge frame enable / Late collision: %d\n" , + !!(flags &BD_TX_HFELC )); +printf (" Control frame / Retransmission Limit: %d\n" , + !!(flags &BD_TX_CFRL )); +printf (" Retry count: %d\n" , + (flags >>BD_TX_RC_OFFSET ) &BD_TX_RC_MASK ); +printf (" Underrun / TCP/IP off-load enable: %d\n" , + !!(flags &BD_TX_TOEUN )); +printf (" Truncation: %d\n" , !!(flags &BD_TX_TR )); +} + +static void print_rx_bd_flags (uint16_t flags) +{ +printf (" Empty: %d\n" , !!(flags &BD_RX_EMPTY )); +printf (" Receive software ownership: %d\n" , !!(flags &BD_RX_RO1 )); +printf (" Wrap: %d\n" , !!(flags &BD_WRAP )); +printf (" Interrupt: %d\n" , !!(flags &BD_INTERRUPT )); +printf (" Last in frame: %d\n" , !!(flags &BD_LAST )); +printf (" First in frame: %d\n" , !!(flags &BD_RX_FIRST )); +printf (" Miss: %d\n" , !!(flags &BD_RX_MISS )); +printf (" Broadcast: %d\n" , !!(flags &BD_RX_BROADCAST )); +printf (" Multicast: %d\n" , !!(flags &BD_RX_MULTICAST )); +printf (" Rx frame length violation: %d\n" , !!(flags &BD_RX_LG )); +printf (" Rx non-octet aligned frame: %d\n" , !!(flags &BD_RX_NO )); +printf (" Short frame: %d\n" , !!(flags &BD_RX_SH )); +printf (" Rx CRC Error: %d\n" , !!(flags &BD_RX_CR )); +printf (" Overrun: %d\n" , !!(flags &BD_RX_OV )); +printf (" Truncation: %d\n" , !!(flags &BD_RX_TR )); +} + + +static void print_bd (eTSEC_rxtx_bd bd,int mode,uint32_t index) +{ +printf ("eTSEC %s Data Buffer Descriptor (%u)\n" , + mode == eTSEC_TRANSMIT ?"Transmit" :"Receive" , + index); +printf (" Flags : 0x%04x\n" , bd.flags); +if (mode == eTSEC_TRANSMIT) { +print_tx_bd_flags (bd.flags); + }else { +print_rx_bd_flags (bd.flags);
hw/net/etsec_rings.c line 106
Quoted 10 lines
hw/net/etsec_rings.c new file +10
-0+ } +printf (" Length : 0x%04x\n" , bd.length); +printf (" Pointer : 0x%08x\n" , bd.bufptr); +} + +#endif /* DEBUG_BD */ + +#ifdef HEX_DUMP + +static void hex_dump (FILE *f,const uint8_t *buf,int size)
can you just use qemu_hexdump?
check util/hexdump.c
Regards,
Peter
Re: [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 2 lines · Peter Crosthwaite
Hi Fabien,
Hi Peter,
Quoted 9 lines · Fabien Chouteau
hw/net/etsec.c line 250
Quoted 3 lines
hw/net/etsec.c new file +3
-0+#ifdef DEBUG_REGISTER +printf ("Write 0x%08x @ 0x" TARGET_FMT_plx" val:0x%08x->0x%08x : %s (%s)\n" , + (unsigned int )value, addr, before, reg->value, reg->name, reg->desc);Last I knew, printf was a bad idea for error messages due to monitor interference issue and nographic mode. But
qemu_logor fprintf(stderr, are both better alternatives.
Fixed.
Quoted 11 lines
hw/net/etsec.c line 329
Quoted 4 lines
hw/net/etsec.c new file +4
-0+static int etsec_can_receive (NetClientState *nc) +{ +/* Yes we always can\ */ +return 1 ;As a general rule this is a bad idea. Multiple ethernet controllers in QEMU have tried this and had issues (particularly with the UBOOT bootloader) with mass packet droppage. But You have access to the information needed (the if conditions in
rx_ring_write) to implement this it seems.
Fixed.
Quoted 6 lines
hw/net/etsec.c line 396
Quoted 3 lines
hw/net/etsec.c new file +3
-0+static int etsec_init (SysBusDevice *dev) +{ +eTSEC *etsec =FROM_SYSBUS (typeof (*etsec), dev);Define and use QOM cast macros instead,
FROM_FOOmacros are deprecated.
Something like:
#define TYPE_ETSEC_COMMON "eTSEC"
#define ETSEC_COMMON(obj) \
OBJECT_CHECK(eTSEC, (obj), TYPE_ETSEC_COMMON)
static int etsec_init(SysBusDevice *dev)
{
eTSEC *etsec = ETSEC_COMMON(dev);?
Quoted 6 lines
hw/net/etsec.c line 399
Quoted 3 lines
hw/net/etsec.c new file +3
-0+ +memory_region_init_io (&etsec->io_area,OBJECT (etsec), &etsec_ops, etsec, +"eTSEC" ,0x1000 );Constant size
memory_region_init_ioshould be migrated to theObject::Initfm.
What is Object::Init()? Do you have an example?
Quoted 9 lines
hw/net/etsec.c line 429
Quoted 6 lines
hw/net/etsec.c new file +6
-0+static void etsec_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = etsec_init;
SysBusDevice::initin depracated. Please useDevice::realizeinstead.
Fixed.
Quoted 7 lines
hw/net/etsec_registers.h line 40
Quoted 4 lines
hw/net/etsec_registers.h new file +4
-0+#define ACC_RW 1/* Read/Write */ +#define ACC_RO 2/* Read Only */ +#define ACC_WO 3/* Write Only */ +#define ACC_w1c 4/* Write 1 to clear */
ACC_W1C. Would it be cleaner with an enum instead?
Fixed.
Quoted 8 lines
hw/net/etsec_rings.c line 106
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+#ifdef HEX_DUMP + +static void hex_dump (FILE *f,const uint8_t *buf,int size)can you just use
qemu_hexdump?check
util/hexdump.c
Didn't know there was one. Fixed.
Thanks for the review.
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Hi Fabien,
Quoted 46 lines · Fabien Chouteau
Quoted 2 lines · Peter Crosthwaite
Hi Fabien,
Hi Peter,
Quoted 9 lines · Fabien Chouteau
hw/net/etsec.c line 250
Quoted 3 lines
hw/net/etsec.c new file +3
-0+#ifdef DEBUG_REGISTER +printf ("Write 0x%08x @ 0x" TARGET_FMT_plx" val:0x%08x->0x%08x : %s (%s)\n" , + (unsigned int )value, addr, before, reg->value, reg->name, reg->desc);Last I knew, printf was a bad idea for error messages due to monitor interference issue and nographic mode. But
qemu_logor fprintf(stderr, are both better alternatives.Fixed.
Quoted 11 lines
hw/net/etsec.c line 329
Quoted 4 lines
hw/net/etsec.c new file +4
-0+static int etsec_can_receive (NetClientState *nc) +{ +/* Yes we always can\ */ +return 1 ;As a general rule this is a bad idea. Multiple ethernet controllers in QEMU have tried this and had issues (particularly with the UBOOT bootloader) with mass packet droppage. But You have access to the information needed (the if conditions in
rx_ring_write) to implement this it seems.Fixed.
Quoted 6 lines
hw/net/etsec.c line 396
Quoted 3 lines
hw/net/etsec.c new file +3
-0+static int etsec_init (SysBusDevice *dev) +{ +eTSEC *etsec =FROM_SYSBUS (typeof (*etsec), dev);Define and use QOM cast macros instead,
FROM_FOOmacros are deprecated.Something like:
#define
TYPE_ETSEC_COMMON"eTSEC"
#defineETSEC_COMMON(obj)\
OBJECT_CHECK(eTSEC, (obj), TYPE_ETSEC_COMMON)
Quoted 6 lines
static int
etsec_init(SysBusDevice *dev){ eTSEC *etsec = ETSEC_COMMON(dev);?
Yes thats the one.
Quoted 10 lines
Quoted 7 lines
hw/net/etsec.c line 399
Quoted 4 lines
hw/net/etsec.c new file +3
-0+ +memory_region_init_io (&etsec->io_area,OBJECT (etsec), &etsec_ops, etsec, +"eTSEC" ,0x1000 );Constant size
memory_region_init_ioshould be migrated to theObject::Initfm.What is
Object::Init()? Do you have an example?
hw/dma/xilinx_axidma.c - xilinx_axidma_init() and xilinx_axidma_realize() has an example of splitting init task between early and late. Note the memory_region_init_io is in the _init.
Regards,
Peter
Quoted 37 lines
Quoted 9 lines
hw/net/etsec.c line 429
Quoted 6 lines
hw/net/etsec.c new file +6
-0+static void etsec_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = etsec_init;
SysBusDevice::initin depracated. Please useDevice::realizeinstead.Fixed.
Quoted 7 lines
hw/net/etsec_registers.h line 40
Quoted 4 lines
hw/net/etsec_registers.h new file +4
-0+#define ACC_RW 1/* Read/Write */ +#define ACC_RO 2/* Read Only */ +#define ACC_WO 3/* Write Only */ +#define ACC_w1c 4/* Write 1 to clear */
ACC_W1C. Would it be cleaner with an enum instead?Fixed.
Quoted 8 lines
hw/net/etsec_rings.c line 106
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+#ifdef HEX_DUMP + +static void hex_dump (FILE *f,const uint8_t *buf,int size)can you just use
qemu_hexdump?check
util/hexdump.cDidn't know there was one. Fixed.
Thanks for the review.
--
Fabien Chouteau
Re: [Qemu-devel] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 7 lines · Peter Crosthwaite
Quoted 7 lines
Quoted 6 lines
hw/net/etsec.c line 399
Quoted 3 lines
hw/net/etsec.c new file +3
-0+ +memory_region_init_io (&etsec->io_area,OBJECT (etsec), &etsec_ops, etsec, +"eTSEC" ,0x1000 );Constant size
memory_region_init_ioshould be migrated to theObject::Initfm.
Quoted 7 lines
Quoted 2 lines
What is
Object::Init()? Do you have an example?
hw/dma/xilinx_axidma.c-xilinx_axidma_init()andxilinx_axidma_realize()has an example of splitting init task between early and late. Note thememory_region_init_iois in the_init.
OK thanks,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
In reply to Fabien ChouteauQuoted 5 lines · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Signed-off-by Fabien Chouteau <[email protected]>From the code comments I gather this has been tested on VxWorks. Has it
been tested on Linux, or anywhere else?
Quoted 8 lines
--- default-configs/ppc-softmmu.mak | 1 + hw/net/Makefile.objs | 1 + hw/net/etsec.c | 472 +++++++++++++++++++++++++++ hw/net/etsec.h | 169 ++++++++++ hw/net/etsec_miim.c | 146 +++++++++ hw/net/etsec_registers.c | 295 +++++++++++++++++ hw/net/etsec_registers.h | 302 ++++++++++++++++++
Quoted 8 lines
hw/net/etsec_rings.c | 673 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 2059 insertions(+) create mode 100644 hw/net/etsec.c create mode 100644 hw/uuunet/etsec.h create mode 100644 hw/net/etsec_miim.c create mode 100644 hw/net/etsec_registers.c create mode 100644 hw/net/etsec_registers.h create mode 100644 hw/net/etsec_rings.c
This should probably be namespaced as something like fsl_etsec.
Quoted 14 lines
default-configs/ppc-softmmu.mak +1
-0@@ -46,3 +46,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y +CONFIG_ETSEC=yhw/net/Makefile.objs +0
-0
hw/net/Makefile.objs obj-$(CONFIG_COLDFIRE) += mcf_fec.o · line 31
Quoted 4 lines
hw/net/Makefile.objs +1
-0@@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o obj-$(CONFIG_PSERIES) += spapr_llan.o obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o
Maybe an fsl_etsec directory?
hw/net/Makefile.objs obj-$(CONFIG_COLDFIRE) += mcf_fec.o
Quoted 6 lines
hw/net/Makefile.objs +6
-0+static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size) +{ + eTSEC *etsec = opaque; + uint32_t reg_index = addr / 4; + eTSEC_Register *reg = NULL; + uint32_t ret = 0x0;
It's always awkward when QEMU's type naming convention collides with names that have pre-existing significant capitalization, but I suspect this ought to be Etsec and EtsecRegister. Or maybe ETSEC and ETSECRegister? Oh well.
Quoted 7 lines
hw/net/Makefile.objs +7
-0+ assert(reg_index < REG_NUMBER); + + reg = &etsec->regs[reg_index]; + + + switch (reg->access) { + case ACC_WO:
hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ ret = 0x00000000; + break; + + case ACC_RW: + case ACC_w1c: + case ACC_RO: + default: + ret = reg->value; + break; + }
Why is "w1c" lowercase when the rest are uppercase? I realize the hardware docs do that, but in this case I don't think that takes precedence over consistent coding style for #defines.
hw/net/Makefile.objs
Quoted 5 lines
hw/net/Makefile.objs +5
-0+#ifdef DEBUG_REGISTER + printf("Read 0x%08x @ 0x" TARGET_FMT_plx + " : %s (%s)\n", + ret, addr, reg->name, reg->desc); +#endif
This is likely to bitrot -- please consider doing something similar to DPRINTF in hw/intc/openpic.c.
Quoted 5 lines
hw/net/Makefile.objs +5
-0+static void write_ievent(eTSEC *etsec, + eTSEC_Register *reg, + uint32_t reg_index, + uint32_t value) +{
hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ if (value & IEVENT_TXF) { + qemu_irq_lower(etsec->tx_irq); + } + if (value & IEVENT_RXF) { + qemu_irq_lower(etsec->rx_irq); + } + + /* Write 1 to clear */ + reg->value &= ~value; +}
What about the error interrupt? You raise it but never lower it that I can see.
TXB/RXB should also be included, and you should only lower the interrupt if neither ?XB nor ?XF are set for a particular direction.
Quoted 20 lines
hw/net/Makefile.objs +20
-0+#ifdef HEX_DUMP +static void hex_dump(FILE *f, const uint8_t *buf, int size) +{ + int len, i, j, c; + + for (i = 0; i < size; i += 16) { + len = size - i; + if (len > 16) { + len = 16; + } + fprintf(f, "%08x ", i); + for (j = 0; j < 16; j++) { + if (j < len) { + fprintf(f, " %02x", buf[i + j]); + } else { + fprintf(f, " "); + } + } + fprintf(f, " "); + for (j = 0; j < len; j++) {
hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ c = buf[i + j]; + if (c < ' ' || c > '~') { + c = '.'; + } + fprintf(f, "%c", c); + } + fprintf(f, "\n"); + } +} +#endif
qemu_hexdump()
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+static int etsec_init(SysBusDevice *dev) +{ + eTSEC *etsec = FROM_SYSBUS(typeof(*etsec), dev);
I was recently yelled at for using FROM_SYSBUS and related deprecated infrastructure -- see http://wiki.qemu.org/QOMConventions
Quoted 15 lines
hw/net/Makefile.objs +15
-0+DeviceState *etsec_create(hwaddr base, + MemoryRegion * mr, + NICInfo * nd, + qemu_irq tx_irq, + qemu_irq rx_irq, + qemu_irq err_irq) +{ + DeviceState *dev; + + dev = qdev_create(NULL, "eTSEC"); + qdev_set_nic_properties(dev, nd); + + if (qdev_init(dev)) { + return NULL; + }
hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, tx_irq); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, rx_irq); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, err_irq); + + memory_region_add_subregion(mr, base, + SYS_BUS_DEVICE(dev)->mmio[0].memory); + + return dev; +}
Do you plan to update hw/ppc/e500.c (or maybe some other platform?) to call this?
If you're centralizing this part of device creation, how about the device tree bits as well?
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+/* eTSEC */ + +#define REG_NUMBER 1024
This is pretty vague.
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +6
-0+DeviceState *etsec_create(hwaddr base, + MemoryRegion *mr, + NICInfo *nd, + qemu_irq tx_irq, + qemu_irq rx_irq, + qemu_irq err_irq);
You've got stuff in this file that isn't properly namespaced for inclusion by arbitrary QEMU code (especially board code that needs to include headers for several devices), such as REG_NUMBER, yet you declare etsec_create here which has to be called from board code.
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +6
-0+#ifdef ETSEC_RING_DEBUG +#define RING_DEBUG(fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__) +#else +#define RING_DEBUG(...) +#endif /* ETSEC_RING_DEBUG */
Please consume the arguments even if debug output is not enabled (so you don't get unused variable warnings), and ideally do a printf inside an if-statement (on a constant so it will be optimized away) so you still get format checking -- again, similar to DPRINTF in hw/intc/openpic.c.
hw/net/Makefile.objs
Quoted 2 lines
hw/net/Makefile.objs +2
-0+#define RING_DEBUG_A(fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__)
"A"?
If this means "always", why not define RING_DEBUG in terms of this?
Quoted 22 lines
hw/net/Makefile.objs +22
-0+#ifdef HEX_DUMP + +static void hex_dump(FILE *f, const uint8_t *buf, int size) +{ + int len, i, j, c; + + for (i = 0; i < size; i += 16) { + len = size - i; + if (len > 16) { + len = 16; + } + fprintf(f, "%08x ", i); + for (j = 0; j < 16; j++) { + if (j < len) { + fprintf(f, " %02x", buf[i + j]); + } else { + fprintf(f, " "); + } + } + fprintf(f, " "); + for (j = 0; j < len; j++) { + c = buf[i + j];
hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ if (c < ' ' || c > '~') { + c = '.'; + } + fprintf(f, "%c", c); + } + fprintf(f, "\n"); + } +} + +#endif
Two instances of this even in the same driver?
Quoted 41 lines
hw/net/Makefile.objs +41
-0+static void fill_rx_bd(eTSEC *etsec, + eTSEC_rxtx_bd *bd, + const uint8_t **buf, + size_t *size) +{ + uint16_t to_write = MIN(etsec->rx_fcb_size + *size - etsec->rx_padding, + etsec->regs[MRBLR].value); + uint32_t bufptr = bd->bufptr; + uint8_t padd[etsec->rx_padding]; + uint8_t rem; + + RING_DEBUG("eTSEC fill Rx buffer @ 0x%08x" + " size:%u(padding + crc:%u) + fcb:%u\n", + bufptr, *size, etsec->rx_padding, etsec->rx_fcb_size); + + bd->length = 0; + if (etsec->rx_fcb_size != 0) { + cpu_physical_memory_write(bufptr, etsec->rx_fcb, etsec->rx_fcb_size); + + bufptr += etsec->rx_fcb_size; + bd->length += etsec->rx_fcb_size; + to_write -= etsec->rx_fcb_size; + etsec->rx_fcb_size = 0; + + } + + if (to_write > 0) { + cpu_physical_memory_write(bufptr, *buf, to_write); + + *buf += to_write; + bufptr += to_write; + *size -= to_write; + + bd->flags &= ~BD_RX_EMPTY; + bd->length += to_write; + } + + if (*size == etsec->rx_padding) { + /* The remaining bytes are for padding which is not actually allocated + in the buffer */ +
hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding); + + if (rem > 0) { + memset(padd, 0x0, sizeof(padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; + cpu_physical_memory_write(bufptr, padd, rem); + } + }
What if *size > 0 && *size < etsec->rx_padding?
hw/net/Makefile.objs
Quoted 11 lines
hw/net/Makefile.objs +11
-0+static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size) +{ + uint32_t fcb_size = 0; + uint8_t prsdep = (etsec->regs[RCTRL].value >> RCTRL_PRSDEP_OFFSET) + & RCTRL_PRSDEP_MASK; + + if (prsdep != 0) { + /* Prepend FCB */ + fcb_size = 8 + 2; /* FCB size + align */ + /* I can't find this 2 bytes alignement in fsl documentation but VxWorks + expects them */
Could these 2 bytes be from RCTRL[PAD], which you seem to ignore?
hw/net/Makefile.objs
Quoted 4 lines
hw/net/Makefile.objs +4
-0+ etsec->rx_padding = 4; + if (size < 60) { + etsec->rx_padding += 60 - size; + }
Could you explain what you're doing with rx_padding?
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+ /* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7;
What about RBDBPH (upper bits of physical address)? Likewise for TX.
Quoted 1 line
+ /* NOTE: non-octet aligned frame is impossible in qemu */
Is it possible in eTSEC?
-Scott
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 8 lines · Scott Wood
Quoted 3 lines · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Signed-off-by Fabien Chouteau <[email protected]>From the code comments I gather this has been tested on VxWorks. Has it been tested on Linux, or anywhere else?
You're right, as I said in the cover letter, this has only been tested on vxWorks.
Quoted 9 lines
Quoted 6 lines
create mode 100644 hw/net/etsec.c create mode 100644 hw/uuunet/etsec.h create mode 100644 hw/net/etsec_miim.c create mode 100644 hw/net/etsec_registers.c create mode 100644 hw/net/etsec_registers.h create mode 100644 hw/net/etsec_rings.cThis should probably be namespaced as something like
fsl_etsec.
Fixed.
Quoted 12 lines
Quoted 12 lines
default-configs/ppc-softmmu.mak +1
-0@@ -46,3 +46,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y +CONFIG_ETSEC=yhw/net/Makefile.objs +0
-1--- a/hw/net/Makefile.objs
Quoted 9 lines
hw/net/Makefile.objs obj-$(CONFIG_COLDFIRE) += mcf_fec.o · line 31
Quoted 6 lines
+++ b/hw/net/Makefile.objs
hw/net/Makefile.objs +1
-0@@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o obj-$(CONFIG_PSERIES) += spapr_llan.o obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.oMaybe an
fsl_etsecdirectory?
Is it really necessary?
Quoted 11 lines
hw/net/Makefile.objs obj-$(CONFIG_COLDFIRE) += mcf_fec.o
Quoted 6 lines
hw/net/Makefile.objs +6
-0+static uint64_t etsec_read(void *opaque, hwaddr addr, unsigned size) +{ + eTSEC *etsec = opaque; + uint32_t reg_index = addr / 4; + eTSEC_Register *reg = NULL; + uint32_t ret = 0x0;It's always awkward when QEMU's type naming convention collides with names that have pre-existing significant capitalization, but I suspect this ought to be Etsec and EtsecRegister. Or maybe ETSEC and ETSECRegister? Oh well.
Oh well... :)
Quoted 14 lines
Quoted 14 lines
hw/net/Makefile.objs +13
-0+ assert(reg_index < REG_NUMBER); + + reg = &etsec->regs[reg_index]; + + + switch (reg->access) { + case ACC_WO: + ret = 0x00000000; + break; + + case ACC_RW: + case ACC_w1c: + case ACC_RO:
Quoted 8 lines
hw/net/Makefile.objs
Quoted 4 lines
hw/net/Makefile.objs +4
-0+ default: + ret = reg->value; + break; + }Why is "w1c" lowercase when the rest are uppercase? I realize the hardware docs do that, but in this case I don't think that takes precedence over consistent coding style for #defines.
Fixed.
Quoted 7 lines
hw/net/Makefile.objs
Quoted 5 lines
hw/net/Makefile.objs +5
-0+#ifdef DEBUG_REGISTER + printf("Read 0x%08x @ 0x" TARGET_FMT_plx + " : %s (%s)\n", + ret, addr, reg->name, reg->desc); +#endifThis is likely to bitrot -- please consider doing something similar to DPRINTF in
hw/intc/openpic.c.
Fixed.
Quoted 20 lines
Quoted 6 lines
hw/net/Makefile.objs +5
-0+static void write_ievent(eTSEC *etsec, + eTSEC_Register *reg, + uint32_t reg_index, + uint32_t value) +{hw/net/Makefile.objs
Quoted 10 lines
hw/net/Makefile.objs +10
-0+ if (value & IEVENT_TXF) { + qemu_irq_lower(etsec->tx_irq); + } + if (value & IEVENT_RXF) { + qemu_irq_lower(etsec->rx_irq); + } + + /* Write 1 to clear */ + reg->value &= ~value; +}What about the error interrupt? You raise it but never lower it that I can see.
Quoted 3 lines
TXB/RXB should also be included, and you should only lower the interrupt if neither ?XB nor ?XF are set for a particular direction.
I don't claim to support all interrupt flags but I will fix this...
Quoted 9 lines
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +5
-0+#ifdef HEX_DUMP +static void hex_dump(FILE *f, const uint8_t *buf, int size) +{ +} +#endif
qemu_hexdump()
Fixed.
Quoted 6 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+static int etsec_init(SysBusDevice *dev) +{ + eTSEC *etsec = FROM_SYSBUS(typeof(*etsec), dev);I was recently yelled at for using
FROM_SYSBUSand related deprecated infrastructure -- see http://wiki.qemu.org/QOMConventions
Me too ;) Fixed.
Quoted 11 lines
hw/net/Makefile.objs
Quoted 8 lines
hw/net/Makefile.objs +6
-0+DeviceState *etsec_create(hwaddr base, + MemoryRegion * mr, + NICInfo * nd, + qemu_irq tx_irq, + qemu_irq rx_irq, + qemu_irq err_irq)Do you plan to update
hw/ppc/e500.c(or maybe some other platform?) to call this?
No I don't, not for the moment. I use it in one of our machine (that is not in mainstream). e500.c would require PCI support I think.
Quoted 3 lines
If you're centralizing this part of device creation, how about the device tree bits as well?
I don't know about device tree...
Quoted 6 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+/* eTSEC */ + +#define REG_NUMBER 1024This is pretty vague.
Fixed.
Quoted 11 lines
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +6
-0+DeviceState *etsec_create(hwaddr base, + MemoryRegion *mr, + NICInfo *nd, + qemu_irq tx_irq, + qemu_irq rx_irq, + qemu_irq err_irq);You've got stuff in this file that isn't properly namespaced for inclusion by arbitrary QEMU code (especially board code that needs to include headers for several devices), such as
REG_NUMBER, yet you declareetsec_createhere which has to be called from board code.
Fixed.
Quoted 12 lines
hw/net/Makefile.objs
Quoted 7 lines
hw/net/Makefile.objs +6
-0+#ifdef ETSEC_RING_DEBUG +#define RING_DEBUG(fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__) +#else +#define RING_DEBUG(...) +#endif /* ETSEC_RING_DEBUG */Please consume the arguments even if debug output is not enabled (so you don't get unused variable warnings), and ideally do a printf inside an if-statement (on a constant so it will be optimized away) so you still get format checking -- again, similar to DPRINTF in
hw/intc/openpic.c.
Fixed.
Quoted 8 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +2
-0+#define RING_DEBUG_A(fmt, ...) printf("%s:%s " fmt, __func__ ,\ + etsec->nic->nc.name, ## __VA_ARGS__)"A"?
If this means "always", why not define
RING_DEBUGin terms of this?
This was just a handy trick, I will remove it.
Quoted 3 lines
Two instances of this even in the same driver?
Fixed.
Quoted 45 lines
Quoted 45 lines
hw/net/Makefile.objs +45
-0+static void fill_rx_bd(eTSEC *etsec, + eTSEC_rxtx_bd *bd, + const uint8_t **buf, + size_t *size) +{ + uint16_t to_write = MIN(etsec->rx_fcb_size + *size - etsec->rx_padding, + etsec->regs[MRBLR].value); + uint32_t bufptr = bd->bufptr; + uint8_t padd[etsec->rx_padding]; + uint8_t rem; + + RING_DEBUG("eTSEC fill Rx buffer @ 0x%08x" + " size:%u(padding + crc:%u) + fcb:%u\n", + bufptr, *size, etsec->rx_padding, etsec->rx_fcb_size); + + bd->length = 0; + if (etsec->rx_fcb_size != 0) { + cpu_physical_memory_write(bufptr, etsec->rx_fcb, etsec->rx_fcb_size); + + bufptr += etsec->rx_fcb_size; + bd->length += etsec->rx_fcb_size; + to_write -= etsec->rx_fcb_size; + etsec->rx_fcb_size = 0; + + } + + if (to_write > 0) { + cpu_physical_memory_write(bufptr, *buf, to_write); + + *buf += to_write; + bufptr += to_write; + *size -= to_write; + + bd->flags &= ~BD_RX_EMPTY; + bd->length += to_write; + } + + if (*size == etsec->rx_padding) { + /* The remaining bytes are for padding which is not actually allocated + in the buffer */ + + rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding); + + if (rem > 0) { + memset(padd, 0x0, sizeof(padd));
Quoted 8 lines
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +6
-0+ etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; + cpu_physical_memory_write(bufptr, padd, rem); + } + }What if *size > 0 && *size <
etsec->rx_padding?
I don't think it's possible...
Quoted 14 lines
hw/net/Makefile.objs
Quoted 12 lines
hw/net/Makefile.objs +11
-0+static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size) +{ + uint32_t fcb_size = 0; + uint8_t prsdep = (etsec->regs[RCTRL].value >> RCTRL_PRSDEP_OFFSET) + & RCTRL_PRSDEP_MASK; + + if (prsdep != 0) { + /* Prepend FCB */ + fcb_size = 8 + 2; /* FCB size + align */ + /* I can't find this 2 bytes alignement in fsl documentation but VxWorks + expects them */Could these 2 bytes be from RCTRL[PAD], which you seem to ignore?
Did you mean RCTRL[PAL]? It could be that.
Quoted 2 lines
Quoted 2 lines
+
etsec->rx_padding= 4;
CRC.
Quoted 5 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+ if (size < 60) { + etsec->rx_padding += 60 - size; + }Could you explain what you're doing with
rx_padding?
Avoiding short frames. I'll add a comments.
Quoted 7 lines
hw/net/Makefile.objs
Quoted 4 lines
hw/net/Makefile.objs +3
-0+ /* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
Quoted 4 lines
Quoted 1 line
+ /* NOTE: non-octet aligned frame is impossible in qemu */
Is it possible in eTSEC?
I think eTSEC can handle it and there's a flag in RxBD for that:
NO | Rx non-octet aligned frame, written by the eTSEC (only valid if L is set). A frame that contained a number of bits not divisible by eight was received.
But we will never receive such frame from QEMU.
Thanks for your review.
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 9 lines · Fabien Chouteau
Quoted 7 lines · Scott Wood
Quoted 3 lines · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Signed-off-by Fabien Chouteau<[email protected]>From the code comments I gather this has been tested on VxWorks. Has it
been tested on Linux, or anywhere else?You're right, as I said in the cover letter, this has only been tested on vxWorks.
Could you please give it a try? IIRC eTSEC support should be in upstream Linux.
[...]
Quoted 6 lines
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ /* ring_base = (etsec->regs[RBASEH].value& 0xF)<< 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value& ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value& ~0x7;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
Why? I thought e500mc and above can access more than 32bits of physical address space? Oh, but they're always DPAA?
Alex
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 5 lines · Alexander Graf
Quoted 4 lines · Fabien Chouteau
Quoted 3 lines · Scott Wood
Quoted 2 lines · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Quoted 8 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line
Signed-off-by Fabien Chouteau<[email protected]>From the code comments I gather this has been tested on VxWorks. Has it
been tested on Linux, or anywhere else?You're right, as I said in the cover letter, this has only been tested on vxWorks.
Could you please give it a try? IIRC eTSEC support should be in upstream Linux.
I don't have time for that. As I said in the cover letter, I submit this patch for those interested in eTSEC, but I won't be able to test/fix it for Linux.
Quoted 9 lines
Quoted 7 lines
Quoted 6 lines
Review
Quoted 4 lines
(quoted diff) +3
-0+ /* ring_base = (etsec->regs[RBASEH].value& 0xF)<< 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value& ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value& ~0x7;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
Why? I thought e500mc and above can access more than 32bits of physical address space?
Yes but this is not emulated by QEMU, right? sizeof (hwaddr) for qemu-system-ppc is 8...
Quoted 2 lines
Oh, but they're always DPAA?
I don't understand...
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 15 lines · Fabien Chouteau
Quoted 4 lines · Alexander Graf
Quoted 3 lines · Fabien Chouteau
Quoted 2 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP
Off-Load, QoS.
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 2 lines
Signed-off-by Fabien Chouteau<[email protected]>From the code comments I gather this has been tested on
VxWorks. Has it
Quoted 3 lines
Quoted 3 lines
Quoted 2 lines
been tested on Linux, or anywhere else?
You're right, as I said in the cover letter, this has only been
tested on vxWorks.
Quoted 1 line
Quoted 7 lines
Quoted 1 line
Could you please give it a try? IIRC eTSEC support should be in
upstream Linux.
Quoted 1 line
I don't have time for that. As I said in the cover letter, I submit this patch for those interested in eTSEC, but I won't be able to test/fix it for Linux.
Could you please at least document more fully the known limitations, such as "I'm only interested in 32bits address spaces"?
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ /* ring_base = (etsec->regs[RBASEH].value& 0xF)<< 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value&~0x7;
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
+
start_bd_addr=bd_addr= etsec->regs[RBPTR0 +ring_nbr].value& ~0x7;
Quoted 1 line
Quoted 1 line
Quoted 1 line
What about RBDBPH (upper bits of physical address)? Likewise for
TX.
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 8 lines
Quoted 1 line
Quoted 1 line
I'm only interested in 32bits address spaces, so RBASEH, TBASEH,
RBDBPH or TBDBPH.
Quoted 2 lines
Why? I thought e500mc and above can access more than 32bits of
physical address space?
Yes but this is not emulated by QEMU, right? sizeof (hwaddr) for qemu-system-ppc is 8...
36bit physical is emulated by QEMU. Currently we put CCSR in a place that would make it difficult to use memory above 4G, but that should change at some point.
Quoted 4 lines
Quoted 2 lines
Oh, but they're always DPAA?
I don't understand...
It doesn't matter, because it's not true. We do support 36-bit address layouts on mpc85xx and mpc86xx, though we don't make it the only supported config in U-Boot as we do on e500mc+.
-Scott
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 13 lines · Scott Wood
Quoted 12 lines · Fabien Chouteau
Quoted 11 lines · Alexander Graf
Quoted 9 lines · Fabien Chouteau
Quoted 7 lines · Scott Wood
Quoted 3 lines · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Signed-off-by Fabien Chouteau<[email protected]>From the code comments I gather this has been tested on VxWorks. Has it
been tested on Linux, or anywhere else?You're right, as I said in the cover letter, this has only been tested on vxWorks.
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
Could you please give it a try? IIRC eTSEC support should be in upstream Linux.
I don't have time for that. As I said in the cover letter, I submit this patch for those interested in eTSEC, but I won't be able to test/fix it for Linux.
Could you please at least document more fully the known limitations, such as "I'm only interested in 32bits address spaces"?
I will, but this device is very complex and I don't even know all the limitation of my implementation ;)
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ /* ring_base = (etsec->regs[RBASEH].value& 0xF)<< 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value& ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value& ~0x7;What about RBDBPH (upper bits of physical address)? Likewise for TX.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
Why? I thought e500mc and above can access more than 32bits of physical address space?
Yes but this is not emulated by QEMU, right? sizeof (hwaddr) for qemu-system-ppc is 8...
36bit physical is emulated by QEMU. Currently we put CCSR in a place that would make it difficult to use memory above 4G, but that should change at some point.
But hwaddr is 32 bits, how could you call cpu_physical_memory_read()? to a 36bits address?
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Am 17.07.2013 um 10:24 schrieb Fabien Chouteau <[email protected]>:
Quoted 32 lines · Scott Wood
Quoted 12 lines · Fabien Chouteau
Quoted 11 lines · Alexander Graf
Quoted 10 lines · Fabien Chouteau
Quoted 8 lines · Scott Wood
Quoted 6 lines · Fabien Chouteau
Quoted 3 lines
This implementation doesn't include ring priority, TCP/IP Off-Load, QoS.
Signed-off-by Fabien Chouteau<[email protected]>From the code comments I gather this has been tested on VxWorks. Has it been tested on Linux, or anywhere else?
You're right, as I said in the cover letter, this has only been tested on vxWorks.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Could you please give it a try? IIRC eTSEC support should be in upstream Linux.
I don't have time for that. As I said in the cover letter, I submit this patch for those interested in eTSEC, but I won't be able to test/fix it for Linux.
Could you please at least document more fully the known limitations, such as "I'm only interested in 32bits address spaces"?
I will, but this device is very complex and I don't even know all the limitation of my implementation ;)
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ /* ring_base = (etsec->regs[RBASEH].value& 0xF)<< 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value& ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value& ~0x7;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
Why? I thought e500mc and above can access more than 32bits of physical address space?
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Yes but this is not emulated by QEMU, right? sizeof (hwaddr) for qemu-system-ppc is 8...
36bit physical is emulated by QEMU. Currently we put CCSR in a place that would make it difficult to use memory above 4G, but that should change at some point.
But hwaddr is 32 bits, how could you call
cpu_physical_memory_read()? to a 36bits address?
8 x 8 = 64, no? :)
Alex
Quoted 5 lines
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 21 lines · Alexander Graf
Am 17.07.2013 um 10:24 schrieb Fabien Chouteau <[email protected]>:
Quoted 17 lines · Scott Wood
Quoted 16 lines · Fabien Chouteau
Quoted 14 lines · Alexander Graf
Quoted 10 lines · Fabien Chouteau
Quoted 7 lines · Scott Wood
Quoted 5 lines · Fabien Chouteau
Review
Quoted 3 lines
(quoted diff) +3
-0+ /* ring_base = (etsec->regs[RBASEH].value& 0xF)<< 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value& ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value& ~0x7;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
Why? I thought e500mc and above can access more than 32bits of physical address space?
Yes but this is not emulated by QEMU, right? sizeof (hwaddr) for qemu-system-ppc is 8...
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
36bit physical is emulated by QEMU. Currently we put CCSR in a place that would make it difficult to use memory above 4G, but that should change at some point.
But hwaddr is 32 bits, how could you call
cpu_physical_memory_read()? to a 36bits address?8 x 8 = 64, no? :)
Oups, I was so sure of myself :)
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
In reply to Fabien ChouteauQuoted 5 lines · Fabien Chouteau
Quoted 2 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
This implementation doesn't include ring priority, TCP/IP
Off-Load, QoS.
Quoted 1 line
Quoted 1 line
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Fabien Chouteau <[email protected]>From the code comments I gather this has been tested on VxWorks.
Has it
Quoted 2 lines
been tested on Linux, or anywhere else?
You're right, as I said in the cover letter, this has only been tested on vxWorks.
OK, I didn't see the cover.
Quoted 11 lines
Quoted 9 lines
hw/net/Makefile.objs obj-$(CONFIG_COLDFIRE) += mcf_fec.o · line 31
Quoted 9 lines
hw/net/Makefile.objs +1
-0@@ -28,6 +28,7 @@ obj-$(CONFIG_COLDFIRE) += mcf_fec.o obj-$(CONFIG_MILKYMIST) += milkymist-minimac2.o obj-$(CONFIG_PSERIES) += spapr_llan.o obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o +obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.oetsec_miim.o
Quoted 1 line
Quoted 4 lines
Quoted 2 lines
Maybe an
fsl_etsecdirectory?Is it really necessary?
Not strictly necessary, but it would help keep things tidy.
Quoted 18 lines
Quoted 9 lines
Quoted 9 lines
hw/net/Makefile.objs +9
-0+static void write_ievent(eTSEC *etsec, + eTSEC_Register *reg, + uint32_t reg_index, + uint32_t value) +{ + if (value & IEVENT_TXF) { + qemu_irq_lower(etsec->tx_irq); + } + if (value & IEVENT_RXF) {Quoted 8 lines
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +6
-0+ qemu_irq_lower(etsec->rx_irq); + } + + /* Write 1 to clear */ + reg->value &= ~value; +}What about the error interrupt? You raise it but never lower it
that I
Quoted 8 lines
Quoted 3 lines
can see.
TXB/RXB should also be included, and you should only lower the
interrupt
Quoted 2 lines
if neither ?XB nor ?XF are set for a particular direction.
I don't claim to support all interrupt flags but I will fix this...
These are interrupt flags that you do set elsewhere.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
hw/net/Makefile.objs +6
-0+DeviceState *etsec_create(hwaddr base, + MemoryRegion * mr, + NICInfo * nd, + qemu_irq tx_irq, + qemu_irq rx_irq, + qemu_irq err_irq)
Quoted 6 lines
Quoted 1 line
Do you plan to update
hw/ppc/e500.c(or maybe some other platform?)to
Quoted 2 lines
call this?
No I don't, not for the moment. I use it in one of our machine (that is not in mainstream).
Someone should, so we can test this without your out-of-tree code.
Quoted 1 line
e500.cwould require PCI support I think.
e500.c has PCI support, but how is that relevant to eTSEC?
Quoted 17 lines
Quoted 2 lines
hw/net/Makefile.objs
Quoted 2 lines
hw/net/Makefile.objs +2
-0+ if (*size == etsec->rx_padding) { + /* The remaining bytes are for padding which is notactually allocated
Quoted 3 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+ in the buffer */ + + rem = MIN(etsec->regs[MRBLR].value - bd->length,
etsec->rx_padding);Quoted 10 lines
Quoted 9 lines
hw/net/Makefile.objs +9
-0+ + if (rem > 0) { + memset(padd, 0x0, sizeof(padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; + cpu_physical_memory_write(bufptr, padd, rem); + } + }
Quoted 3 lines
Quoted 1 line
What if *size > 0 && *size <
etsec->rx_padding?I don't think it's possible...
Maybe throw in an assertion, then?
I can see how it might not be possible if rx_padding is being used for padding a short frame, since MRBLR must be a multiple of 64, but what if it's 4 bytes for CRC?
Quoted 12 lines
Quoted 1 line
Quoted 1 line
+static void rx_init_frame(eTSEC *etsec, const
uint8_t*buf,
size_tsize)Quoted 3 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+{ + uint32_t fcb_size = 0; + uint8_t prsdep = (etsec->regs[RCTRL].value >>
RCTRL_PRSDEP_OFFSET)Quoted 6 lines
hw/net/Makefile.objs
Quoted 6 lines
hw/net/Makefile.objs +6
-0+ & RCTRL_PRSDEP_MASK; + + if (prsdep != 0) { + /* Prepend FCB */ + fcb_size = 8 + 2; /* FCB size + align */ + /* I can't find this 2 bytes alignement in fsl
Quoted 6 lines
documentation but VxWorks
Quoted 3 lines
Quoted 1 line
+ expects them */
Could these 2 bytes be from RCTRL[PAD], which you seem to ignore?
Did you mean RCTRL[PAL]? It could be that.
Yes, sorry.
Quoted 11 lines
Quoted 1 line
Quoted 1 line
+
etsec->rx_padding= 4;CRC.
Quoted 5 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+ if (size < 60) { + etsec->rx_padding += 60 - size; + }Could you explain what you're doing with
rx_padding?Avoiding short frames. I'll add a comments.
This is for when RCTRL[RSF] is set, to accept short frames? Is it documented anywhere that these frames are zero-padded to 64 bytes on rx? If not, is this the observed behavior of real hardware?
In any case, please add some comments.
Quoted 10 lines
Quoted 3 lines
hw/net/Makefile.objs
Quoted 3 lines
hw/net/Makefile.objs +3
-0+ /* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 +ring_nbr].value & ~0x7;
Quoted 2 lines
What about RBDBPH (upper bits of physical address)? Likewise for
TX.
Quoted 1 line
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
When adding code to mainline, it's about more than what you're personally interested in...
Could you at least have a way to diagnose when the guest OS tries to use some functionality that you don't support, rather than silently doing the wrong thing?
Quoted 6 lines
Quoted 1 line
Quoted 1 line
+ /* NOTE: non-octet aligned frame is impossible in
qemu */
Quoted 3 lines
Is it possible in eTSEC?
Quoted 6 lines
I think eTSEC can handle it and there's a flag in RxBD for that:
NO | Rx non-octet aligned frame, written by the eTSEC (only valid if L is set). A frame that contained a number of bits not divisible by eight was received.
But we will never receive such frame from QEMU.
OK, it's just an error detection flag, not something that's actually supported.
-Scott
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 12 lines · Scott Wood
Quoted 8 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
+obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o
Maybe an
fsl_etsecdirectory?Is it really necessary?
Not strictly necessary, but it would help keep things tidy.
I will try :)
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
hw/net/etsec.c line 453
Quoted 7 lines
hw/net/etsec.c new file +6
-0+DeviceState *etsec_create (hwaddr base, +MemoryRegion * mr, +NICInfo * nd, +qemu_irq tx_irq, +qemu_irq rx_irq, +qemu_irq err_irq)Do you plan to update
hw/ppc/e500.c(or maybe some other platform?) to call this?
Quoted 7 lines
Quoted 1 line
No I don't, not for the moment. I use it in one of our machine (that is not in mainstream).
Someone should, so we can test this without your out-of-tree code.
Quoted 1 line
e500.cwould require PCI support I think.
e500.chas PCI support, but how is that relevant to eTSEC?
I guess it's not. We would have to remove:
if (pci_bus) {
/* Register network interfaces. */
for (i = 0; i < nb_nics; i++) {
pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL);
}
}Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
Quoted 5 lines
hw/net/etsec_rings.c new file +4
-0+if (*size == etsec->rx_padding) { +/* The remaining bytes are for padding which is not actually allocated +in the buffer */ +hw/net/etsec_rings.c line 467
Quoted 10 lines
hw/net/etsec_rings.c new file +10
-0+ rem =MIN (etsec->regs[MRBLR ].value - bd->length, etsec->rx_padding); + +if (rem >0 ) { +memset (padd,0x0 ,sizeof (padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; +cpu_physical_memory_write (bufptr, padd, rem); + } + }What if *size > 0 && *size <
etsec->rx_padding?
Quoted 6 lines
Quoted 1 line
I don't think it's possible...
Maybe throw in an assertion, then?
I can see how it might not be possible if
rx_paddingis being used for padding a short frame, since MRBLR must be a multiple of 64, but what if it's 4 bytes for CRC?
Can you explain a possible error scenario?
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
hw/net/etsec_rings.c line 480
Quoted 11 lines
hw/net/etsec_rings.c new file +11
-0+static void rx_init_frame (eTSEC *etsec,const uint8_t *buf,size_t size) +{ +uint32_t fcb_size =0 ; +uint8_t prsdep = (etsec->regs[RCTRL ].value >>RCTRL_PRSDEP_OFFSET ) + &RCTRL_PRSDEP_MASK ; + +if (prsdep !=0 ) { +/* Prepend FCB */ + fcb_size =8 +2 ;/* FCB size + align */ +/* I can't find this 2 bytes alignement in fsl documentation but VxWorks +expects them */ Could these 2 bytes be from RCTRL[PAD], which you seem to ignore?
Quoted 4 lines
Quoted 1 line
Did you mean RCTRL[PAL]? It could be that.
Yes, sorry.
Thanks for pointing it ;)
Quoted 8 lines
Quoted 8 lines
Quoted 1 line
Quoted 1 line
+
etsec->rx_padding= 4;CRC.
Quoted 4 lines
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+if (size <60 ) { + etsec->rx_padding +=60 - size; + }
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Could you explain what you're doing with
rx_padding?Avoiding short frames. I'll add a comments.
This is for when RCTRL[RSF] is set, to accept short frames? Is it documented anywhere that these frames are zero-padded to 64 bytes on rx? If not, is this the observed behavior of real hardware?
In any case, please add some comments.
Actually, this might be obsolete. At the time QEMU was sending short frames, but vxWorks drop them, so I made this change to always have 64B frames. Now I have another patch to fix this and I will remove this hack and implement RCTRL[RSF].
Quoted 11 lines
Quoted 8 lines
Quoted 6 lines
hw/net/etsec_rings.c line 567
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+/* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7 ; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7 ;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
When adding code to mainline, it's about more than what you're personally interested in...
If I'm not "personally" interested, I will not have time to develop or test a feature. If someone wants to do 36bit addressing, feel free to do it, that's why I send the patch on QEMU-devel, but I won't implement full support of eTSEC myself...
Quoted 4 lines
Could you at least have a way to diagnose when the guest OS tries to use some functionality that you don't support, rather than silently doing the wrong thing?
This device is so complex, detecting unsupported features would take too much work.
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 35 lines · Fabien Chouteau
Quoted 12 lines · Scott Wood
Quoted 8 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
+obj-$(CONFIG_ETSEC) += etsec.o etsec_registers.o etsec_rings.o etsec_miim.o
Maybe an
fsl_etsecdirectory?Is it really necessary?
Not strictly necessary, but it would help keep things tidy.
I will try :)
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
hw/net/etsec.c line 453
Quoted 7 lines
hw/net/etsec.c new file +6
-0+DeviceState *etsec_create (hwaddr base, +MemoryRegion * mr, +NICInfo * nd, +qemu_irq tx_irq, +qemu_irq rx_irq, +qemu_irq err_irq)Do you plan to update
hw/ppc/e500.c(or maybe some other platform?) to call this?Quoted 7 lines
Quoted 1 line
No I don't, not for the moment. I use it in one of our machine (that is not in mainstream).
Someone should, so we can test this without your out-of-tree code.
Quoted 1 line
e500.cwould require PCI support I think.
e500.chas PCI support, but how is that relevant to eTSEC?
Quoted 8 lines
I guess it's not. We would have to remove:
if (pci_bus) { /* Register network interfaces. */ for (i = 0; i < nb_nics; i++) { pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL); } }
Well, this code is pretty broken anyways. It should honor the IF type that we request from it. Then we can also add eTSEC as one.
Quoted 89 lines
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 6 lines
hw/net/etsec_rings.c new file +4
-0+if (*size == etsec->rx_padding) { +/* The remaining bytes are for padding which is not actually allocated +in the buffer */ +hw/net/etsec_rings.c line 467
Quoted 10 lines
hw/net/etsec_rings.c new file +10
-0+ rem =MIN (etsec->regs[MRBLR ].value - bd->length, etsec->rx_padding); + +if (rem >0 ) { +memset (padd,0x0 ,sizeof (padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; +cpu_physical_memory_write (bufptr, padd, rem); + } + }What if *size > 0 && *size <
etsec->rx_padding?Quoted 6 lines
Quoted 1 line
I don't think it's possible...
Maybe throw in an assertion, then?
I can see how it might not be possible if
rx_paddingis being used for padding a short frame, since MRBLR must be a multiple of 64, but what if it's 4 bytes for CRC?Can you explain a possible error scenario?
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
hw/net/etsec_rings.c line 480
Quoted 11 lines
hw/net/etsec_rings.c new file +11
-0+static void rx_init_frame (eTSEC *etsec,const uint8_t *buf,size_t size) +{ +uint32_t fcb_size =0 ; +uint8_t prsdep = (etsec->regs[RCTRL ].value >>RCTRL_PRSDEP_OFFSET ) + &RCTRL_PRSDEP_MASK ; + +if (prsdep !=0 ) { +/* Prepend FCB */ + fcb_size =8 +2 ;/* FCB size + align */ +/* I can't find this 2 bytes alignement in fsl documentation but VxWorks +expects them */ Could these 2 bytes be from RCTRL[PAD], which you seem to ignore?
Quoted 4 lines
Quoted 1 line
Did you mean RCTRL[PAL]? It could be that.
Yes, sorry.
Thanks for pointing it ;)
Quoted 8 lines
Quoted 8 lines
Quoted 1 line
Quoted 1 line
+
etsec->rx_padding= 4;CRC.
Quoted 4 lines
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+if (size <60 ) { + etsec->rx_padding +=60 - size; + }Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Could you explain what you're doing with
rx_padding?Avoiding short frames. I'll add a comments.
This is for when RCTRL[RSF] is set, to accept short frames? Is it documented anywhere that these frames are zero-padded to 64 bytes on rx? If not, is this the observed behavior of real hardware?
In any case, please add some comments.
Actually, this might be obsolete. At the time QEMU was sending short frames, but vxWorks drop them, so I made this change to always have 64B frames. Now I have another patch to fix this and I will remove this hack and implement RCTRL[RSF].
Quoted 11 lines
Quoted 8 lines
Quoted 6 lines
hw/net/etsec_rings.c line 567
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+/* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7 ; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7 ;What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
When adding code to mainline, it's about more than what you're personally interested in...
If I'm not "personally" interested, I will not have time to develop or test a feature. If someone wants to do 36bit addressing, feel free to do it, that's why I send the patch on QEMU-devel, but I won't implement full support of eTSEC myself...
Quoted 7 lines
Quoted 4 lines
Could you at least have a way to diagnose when the guest OS tries to use some functionality that you don't support, rather than silently doing the wrong thing?
This device is so complex, detecting unsupported features would take too much work.
In this case a simple if(<upper bits of addresses>) hw_error(...) would be good enough :). It's just to make sure that all this valuable knowledge doesn't get lost any someone who eventually does run into 36bit addressing doesn't have to debug for a week to figure out who randomly overwrites his kernel ;).
Alex
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 29 lines · Alexander Graf
Quoted 26 lines · Fabien Chouteau
Quoted 7 lines · Scott Wood
Quoted 6 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 3 lines · Fabien Chouteau
hw/net/etsec_rings.c new file +3
-0+/* ring_base = (etsec->regs[RBASEH].value & 0xF) << 32; */ + ring_base += etsec->regs[RBASE0 + ring_nbr].value & ~0x7 ; + start_bd_addr = bd_addr = etsec->regs[RBPTR0 + ring_nbr].value & ~0x7 ;Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
What about RBDBPH (upper bits of physical address)? Likewise for TX.
I'm only interested in 32bits address spaces, so RBASEH, TBASEH, RBDBPH or TBDBPH.
When adding code to mainline, it's about more than what you're personally interested in...
If I'm not "personally" interested, I will not have time to develop or test a feature. If someone wants to do 36bit addressing, feel free to do it, that's why I send the patch on QEMU-devel, but I won't implement full support of eTSEC myself...
Quoted 4 lines
Could you at least have a way to diagnose when the guest OS tries to use some functionality that you don't support, rather than silently doing the wrong thing?
Quoted 5 lines
Quoted 2 lines
This device is so complex, detecting unsupported features would take too much work.
In this case a simple if(<upper bits of addresses>)
hw_error(...)would be good enough :). It's just to make sure that all this valuable knowledge doesn't get lost any someone who eventually does run into 36bit addressing doesn't have to debug for a week to figure out who randomly overwrites his kernel ;).
Since hwaddr is 64bits, I will add RBASEH, TBASEH, RBDBPH and TBDBPH support...
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
In reply to Fabien ChouteauQuoted 25 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 4 lines · Fabien Chouteau
Quoted 3 lines · Scott Wood
Review
Quoted 2 lines · Fabien Chouteau
(quoted diff) +2
-0+ if (*size == etsec->rx_padding) { + /* The remaining bytes are for padding which is notactually allocated
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
hw/net/etsec_rings.c
Quoted 3 lines
hw/net/etsec_rings.c new file +3
-0+in the buffer */ + + rem = MIN(etsec->regs[MRBLR].value - bd->length,
etsec->rx_padding);Quoted 14 lines
Quoted 13 lines
Quoted 11 lines
hw/net/etsec_rings.c line 467
Quoted 9 lines
hw/net/etsec_rings.c new file +9
-0+ +if (rem >0 ) { +memset (padd,0x0 ,sizeof (padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; +cpu_physical_memory_write (bufptr, padd, rem); + } + }What if *size > 0 && *size <
etsec->rx_padding?I don't think it's possible...
Quoted 7 lines
Quoted 3 lines
Maybe throw in an assertion, then?
I can see how it might not be possible if
rx_paddingis being usedfor padding a short frame, since MRBLR must be a multiple of 64, but what if it's 4 bytes for CRC?
Quoted 1 line
Can you explain a possible error scenario?
126 byte packet, no fcb. rx_padding is 4 for CRC. Suppose MRBLR is 128. Wouldn't *size be 2 here?
Quoted 7 lines
Quoted 4 lines
Could you at least have a way to diagnose when the guest OS tries to use some functionality that you don't support, rather than silently doing the wrong thing?
This device is so complex, detecting unsupported features would take too much work.
I was thinking along the lines of marking registers and bits within registers as supported (or which are properly no-ops in QEMU) -- and warning the first time you see a non-default-value write to an unsupported field or register. It could save a lot of debugging.
-Scott
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 24 lines · Scott Wood
Quoted 23 lines · Fabien Chouteau
Quoted 22 lines · Scott Wood
Quoted 20 lines · Fabien Chouteau
Quoted 17 lines · Scott Wood
Quoted 4 lines · Fabien Chouteau
hw/net/etsec_rings.c new file +4
-0+if (*size == etsec->rx_padding) { +/* The remaining bytes are for padding which is not actually allocated +in the buffer */ +hw/net/etsec_rings.c line 467
Quoted 10 lines
hw/net/etsec_rings.c new file +10
-0+ rem =MIN (etsec->regs[MRBLR ].value - bd->length, etsec->rx_padding); + +if (rem >0 ) { +memset (padd,0x0 ,sizeof (padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; +cpu_physical_memory_write (bufptr, padd, rem); + } + }What if *size > 0 && *size <
etsec->rx_padding?I don't think it's possible...
Quoted 9 lines
Quoted 6 lines
Quoted 4 lines
Maybe throw in an assertion, then?
I can see how it might not be possible if
rx_paddingis being used for padding a short frame, since MRBLR must be a multiple of 64, but what if it's 4 bytes for CRC?Can you explain a possible error scenario?
126 byte packet, no fcb.
rx_paddingis 4 for CRC. Suppose MRBLR is 128. Wouldn't *size be 2 here?
Yes, at the end of the function, but then rx_padding is 2 as well.
value of "to_write" will be 126:
*size = etsec->rx_remaining_data + etsec->rx_padding;
= 126 + 4;
= 130;to_write = MIN(etsec->rx_fcb_size + *size - etsec->rx_padding, etsec->regs[MRBLR].value);
= MIN(0 + 130 - 4, 128);
= MIN(126, 128);
= 126;So we write the packet in the first part of the BD, and there's 2 bytes left in the BD.
*size -= to_write;
= 4;
bd->length = to_write;
= 126;So *size == etsec->rx_padding (This is expected as the first write operation can only write data and no padding, I will comment this fact)
rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding);
= MIN(128 - 126, 4);
= MIN(2, 4);
= 2;We write 2 bytes of padding.
etsec->rx_padding -= rem;
= 2;
*size -= rem;
= 2;
bd->length += rem;
= 128;The BD is full, we will have to put the rest of padding in the next one.
Quoted 10 lines
Quoted 7 lines
Quoted 4 lines
Could you at least have a way to diagnose when the guest OS tries to use some functionality that you don't support, rather than silently doing the wrong thing?
This device is so complex, detecting unsupported features would take too much work.
I was thinking along the lines of marking registers and bits within registers as supported (or which are properly no-ops in QEMU) -- and warning the first time you see a non-default-value write to an unsupported field or register. It could save a lot of debugging.
I think we'll spend more time implementing this than debugging. Another solution is to enable debug output and see which registers are read or write.
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 33 lines · Fabien Chouteau
Quoted 7 lines · Scott Wood
Quoted 6 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 4 lines · Fabien Chouteau
Quoted 3 lines · Scott Wood
Review
Quoted 2 lines · Fabien Chouteau
(quoted diff) +2
-0+ if (*size == etsec->rx_padding) { + /* The remaining bytes are for padding which is notactually allocated
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ in the buffer */ + + rem = MIN(etsec->regs[MRBLR].value - bd->length,
etsec->rx_padding);Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
(quoted diff) +9
-0+ + if (rem > 0) { + memset(padd, 0x0, sizeof(padd)); + etsec->rx_padding -= rem; + *size -= rem; + bd->length += rem; + cpu_physical_memory_write(bufptr, padd, rem); + } + }Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
What if *size > 0 && *size <
etsec->rx_padding?I don't think it's possible...
Maybe throw in an assertion, then?
I can see how it might not be possible if
rx_paddingis beingused for padding a short frame, since MRBLR must be a multiple of 64, but what if it's 4 bytes for CRC?
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Can you explain a possible error scenario?
126 byte packet, no fcb.
rx_paddingis 4 for CRC. Suppose MRBLRis 128. Wouldn't *size be 2 here?
Quoted 1 line
Yes, at the end of the function, but then
rx_paddingis 2 as well.
How is rx_padding 2? rx_init_frame() will set it to 4 (since the packet size is not less than 60). The only other place I see that modifies rx_padding is "etsec->rx_padding -= rem", but that doesn't happen because the "*size == etsec->rx_padding" check happens first.
Quoted 29 lines
value of "
to_write" will be 126:*size = etsec->rx_remaining_data + etsec->rx_padding; = 126 + 4; = 130;to_write = MIN(etsec->rx_fcb_size + *size - etsec->rx_padding, etsec->regs[MRBLR].value); = MIN(0 + 130 - 4, 128); = MIN(126, 128); = 126;So we write the packet in the first part of the BD, and there's 2 bytes left in the BD.
*size -= to_write; = 4; bd->length = to_write; = 126;So *size ==
etsec->rx_padding(This is expected as the first write operation can only write data and no padding, I will comment this fact)rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding); = MIN(128 - 126, 4); = MIN(2, 4); = 2;We write 2 bytes of padding.
Quoted 8 lines
etsec->rx_padding -= rem; = 2; *size -= rem; = 2; bd->length += rem; = 128;The BD is full, we will have to put the rest of padding in the next one.
What rest of padding? I thought you said rx_padding was 2 somehow? If that were true, then it would be zero at the end.
Quoted 11 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Could you at least have a way to diagnose when the guest OS
tries to
Quoted 1 line
Quoted 1 line
Quoted 1 line
use some functionality that you don't support, rather than
silently
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines
doing the wrong thing?
This device is so complex, detecting unsupported features would
take too
Quoted 2 lines
Quoted 1 line
much work.
Quoted 7 lines
Quoted 1 line
I was thinking along the lines of marking registers and bits within
registers as supported (or which are properly no-ops in QEMU) -- and warning the first time you see a non-default-value write to an unsupported field or register. It could save a lot of debugging.
Quoted 1 line
I think we'll spend more time implementing this than debugging. Another solution is to enable debug output and see which registers are read or write.
I don't think it'd be that hard -- you already have an array of registers. The information could easily go in there, and be checked by common infrastructure.
-Scott
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 11 lines · Scott Wood
Quoted 8 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
Can you explain a possible error scenario?
126 byte packet, no fcb.
rx_paddingis 4 for CRC. Suppose MRBLR is 128. Wouldn't *size be 2 here?Yes, at the end of the function, but then
rx_paddingis 2 as well.How is
rx_padding2?rx_init_frame()will set it to 4 (since the packet size is not less than 60).
Yes, rx_padding == 4 at the beginning of fill_rx_bd() but rx_padding will be 2 at the end.
Quoted 36 lines
Quoted 36 lines
value of "
to_write" will be 126:*size = etsec->rx_remaining_data + etsec->rx_padding; = 126 + 4; = 130;to_write = MIN(etsec->rx_fcb_size + *size - etsec->rx_padding, etsec->regs[MRBLR].value); = MIN(0 + 130 - 4, 128); = MIN(126, 128); = 126;So we write the packet in the first part of the BD, and there's 2 bytes left in the BD.
*size -= to_write; = 4; bd->length = to_write; = 126;So *size ==
etsec->rx_padding(This is expected as the first write operation can only write data and no padding, I will comment this fact)rem = MIN(etsec->regs[MRBLR].value - bd->length, etsec->rx_padding); = MIN(128 - 126, 4); = MIN(2, 4); = 2;We write 2 bytes of padding.
etsec->rx_padding -= rem; = 2; *size -= rem; = 2; bd->length += rem; = 128;
Quoted 4 lines
Quoted 1 line
The BD is full, we will have to put the rest of padding in the next one.
What rest of padding? I thought you said
rx_paddingwas 2 somehow? If that were true, then it would be zero at the end.
Read my description again.
Regards,
Signature · 1 line
Fabien Chouteau
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 10 lines · Fabien Chouteau
Quoted 2 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
The BD is full, we will have to put the rest of padding in the
next one.
Quoted 2 lines
What rest of padding? I thought you said
rx_paddingwas 2somehow? If that were true, then it would be zero at the end.
Quoted 1 line
Read my description again.
OK, I was confused by your answering "yes" to "wouldn't *size be 2 here" -- I thought it was clear from the context that I was talking about at the time of the "if (*size == etsec->rx_padding)" statement. Maybe you thought I was talking about what would happen at that if-statement in the next descriptor?
In any case, it's a bit hard to follow this code. rx_fcb_size is included in to_write, but not in *size. rx_padding is included in *size, but not in to_write. And it generally makes me nervous to see code that will go into an infinite loop (or other odd behavior) unless an exact-equality terminating condition is met, especially when it's as complicated as this, without an assertion to check for the bad case (even if it looks like it could never happen).
-Scott
Re: [Qemu-devel] [Qemu-ppc] [PATCH 2/2] Add Enhanced Three-Speed Ethernet Controller (eTSEC)
Quoted 10 lines · Scott Wood
Quoted 8 lines · Fabien Chouteau
Quoted 5 lines · Scott Wood
Quoted 1 line · Fabien Chouteau
The BD is full, we will have to put the rest of padding in the next one.
What rest of padding? I thought you said
rx_paddingwas 2 somehow? If that were true, then it would be zero at the end.Read my description again.
Quoted 7 lines
OK, I was confused by your answering "yes" to "wouldn't *size be 2 here" -- I thought it was clear from the context that I was talking about at the time of the "if (*size ==
etsec->rx_padding)" statement. Maybe you thought I was talking about what would happen at that if-statement in the next descriptor?In any case, it's a bit hard to follow this code.
I agree it's a little bit hard, I will add some comments to make it clearer.
Quoted 1 line
rx_fcb_sizeis included into_write, but not in *size.
FCB is not considered as part of the packet, so not in remaining_data.
Quoted 1 line
rx_paddingis included in *size, but not into_write.
Padding on the other side is considered as part of the packet but not allocated in the buffer.
Quoted 6 lines
And it generally makes me nervous to see code that will go into an infinite loop (or other odd behavior) unless an exact-equality terminating condition is met, especially when it's as complicated as this, without an assertion to check for the bad case (even if it looks like it could never happen).
For me it is more confusing to see a less-or-equal when equal is the necessary and sufficient condition. It will be even harder to understand the code...
I will modify the code a bit, tell me if it's clearer.
Regards,
Signature · 1 line
Fabien Chouteau