[Qemu-devel] [PATCH v2 06/20] arm: add Faraday FTMAC110 10/100Mbps ethernet support

2013-01-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTMAC110 is a high quality 10/100 Ethernet controller with DMA function.
It includes an AHB wrapper, DMA engine, on-chip memories (TX FIFO and RX
FIFO), MAC, and MII or RMII interface.

The FTMAC110 is an Ethernet controller that provides AHB master capability
and is in full compliance with the IEEE 802.3 10/100 Mbps specifications.
The FTMAC110 DMA controller handles all data transfers between system memory
and on-chip memories. It supports half-word data transfer for Linux.
With the DMA engine, it can reduce CPU loading, maximize the performance
and minimize the FIFO size.

It also has on-chip memories for buffering, so an external local buffer memory
is not needed. The MII or RMII interface can support two specific data rates,
10 Mbps and 100 Mbps. The functionality is identical at both data rates, as is
the signal timing relationship. The only difference between 10 and 100 Mbps
operations is the nominal clock frequency.

It also supports Wake-On-LAN function with three wake-up events:
Link status change, magic packet, and wake-up frame.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/ftmac110.c |  591 +
 hw/ftmac110.h |  131 +
 2 files changed, 722 insertions(+)
 create mode 100644 hw/ftmac110.c
 create mode 100644 hw/ftmac110.h

diff --git a/hw/ftmac110.c b/hw/ftmac110.c
new file mode 100644
index 000..4c2c125
--- /dev/null
+++ b/hw/ftmac110.c
@@ -0,0 +1,591 @@
+/*
+ * QEMU model of the FTMAC110 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2.
+ */
+
+#include sysbus.h
+#include sysemu/sysemu.h
+#include net/net.h
+
+#include faraday.h
+#include ftmac110.h
+
+#define TYPE_FTMAC110ftmac110
+
+typedef struct Ftmac110State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+QEMUTimer *qtimer;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+
+uint32_t isr;
+uint32_t ier;
+uint32_t mhash[2];
+uint32_t tx_bar;
+uint32_t rx_bar;
+uint32_t tx_idx;
+uint32_t rx_idx;
+uint32_t maccr;
+uint32_t macsr;
+uint32_t phycr;
+uint32_t phycr_rd;
+
+struct {
+uint8_t  buf[2048];
+uint32_t len;
+} txbuff;
+
+uint32_t rx_pkt;
+uint32_t rx_bcst;
+uint32_t rx_mcst;
+uint16_t rx_runt;
+uint16_t rx_drop;
+uint16_t rx_crc;
+uint16_t rx_ftl;
+uint32_t tx_pkt;
+
+} ftmac110_state;
+
+#define FTMAC110(obj) \
+OBJECT_CHECK(ftmac110_state, obj, TYPE_FTMAC110)
+
+static uint8_t bitrev8(uint8_t v)
+{
+int i;
+uint8_t r = 0;
+for (i = 0; i  8; ++i) {
+if (v  (1  i)) {
+r |= (1  (7 - i));
+}
+}
+return r;
+}
+
+static int ftmac110_mcast_hash(int len, const uint8_t *p)
+{
+#define CRCPOLY_LE 0xedb88320
+int i;
+uint32_t crc = 0x;
+
+while (len--) {
+crc ^= *p++;
+for (i = 0; i  8; i++) {
+crc = (crc  1) ^ ((crc  1) ? CRCPOLY_LE : 0);
+}
+}
+
+/* Reverse CRC32 and return MSB 6 bits only */
+return bitrev8(crc  24)  2;
+}
+
+static void ftmac110_read_desc(hwaddr addr, void *desc)
+{
+int i;
+uint32_t *p = desc;
+
+cpu_physical_memory_read(addr, desc, 16);
+
+for (i = 0; i  16; i += 4) {
+*p = le32_to_cpu(*p);
+}
+}
+
+static void ftmac110_write_desc(hwaddr addr, void *desc)
+{
+int i;
+uint32_t *p = desc;
+
+for (i = 0; i  16; i += 4) {
+*p = cpu_to_le32(*p);
+}
+
+cpu_physical_memory_write(addr, desc, 16);
+}
+
+static void ftmac110_update_irq(ftmac110_state *s)
+{
+if (s-isr  s-ier) {
+qemu_set_irq(s-irq, 1);
+} else {
+qemu_set_irq(s-irq, 0);
+}
+}
+
+static int ftmac110_can_receive(NetClientState *nc)
+{
+ftmac110_state *s = FTMAC110(DO_UPCAST(NICState, nc, nc)-opaque);
+ftmac110_rxdesc_t rxd;
+hwaddr off = s-rx_bar + s-rx_idx * sizeof(rxd);
+
+if ((s-maccr  (MACCR_RCV_EN | MACCR_RDMA_EN))
+!= (MACCR_RCV_EN | MACCR_RDMA_EN)) {
+return 0;
+}
+
+ftmac110_read_desc(off, rxd);
+
+return rxd.owner;
+}
+
+static ssize_t ftmac110_receive(NetClientState *nc,
+const uint8_t  *buf,
+size_t  size)
+{
+const uint8_t *ptr = buf;
+hwaddr off;
+size_t len;
+ftmac110_rxdesc_t rxd;
+ftmac110_state *s = FTMAC110(DO_UPCAST(NICState, nc, nc)-opaque);
+int bcst, mcst;
+
+if ((s-maccr  (MACCR_RCV_EN | MACCR_RDMA_EN))
+!= (MACCR_RCV_EN | MACCR_RDMA_EN)) {
+return -1;
+}
+
+/* if it's a broadcast */
+if ((buf[0] == 0xff)  (buf[1] == 0xff)  (buf[2] == 0xff)
+ (buf[3] == 0xff)  (buf[4] == 0xff)  (buf[5] == 0xff)) {
+bcst = 1;
+if (!(s-maccr  MACCR_RCV_ALL)  !(s-maccr  MACCR_RX_BROADPKT)) {
+

Re: [Qemu-devel] [PATCH v2 06/20] arm: add Faraday FTMAC110 10/100Mbps ethernet support

2013-01-25 Thread Paul Brook
 The FTMAC110 is a high quality 10/100 Ethernet controller 

Which looks largely the same as the other ethernet controller you added in the 
previous patch.

Paul