qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 04/18] hw: add QEMU model for Faraday 1Gbps Ethernet


From: Dante
Subject: [Qemu-devel] [PATCH 04/18] hw: add QEMU model for Faraday 1Gbps Ethernet MAC
Date: Fri, 18 Jan 2013 14:28:12 +0800

Signed-off-by: Kuo-Jung Su <address@hidden>
---
 hw/ftgmac100.c |  621 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ftgmac100.h |  191 +++++++++++++++++
 2 files changed, 812 insertions(+)
 create mode 100644 hw/ftgmac100.c
 create mode 100644 hw/ftgmac100.h

diff --git a/hw/ftgmac100.c b/hw/ftgmac100.c
new file mode 100644
index 0000000..d66c719
--- /dev/null
+++ b/hw/ftgmac100.c
@@ -0,0 +1,621 @@
+/*
+ * QEMU model of the FTGMAC100 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Copyright (C) 2012 Dante Su <address@hidden>
+ *
+ * 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 "sysbus.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+
+#include "ftgmac100.h"
+
+typedef struct {
+    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 hptx_bar;
+    uint32_t tx_idx;
+    uint32_t rx_idx;
+    uint32_t hptx_idx;
+    uint32_t maccr;
+    uint32_t macsr;
+    uint32_t phycr;
+    uint32_t phycr_rd;
+    
+    struct {
+        uint8_t  buf[9220];
+        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;
+
+} ftgmac100_state;
+
+static inline uint8_t bitrev8(uint8_t v)
+{
+    uint8_t r = 0;
+    int i;    
+    for(i = 0; i < 8; ++i) {
+        if (v & (1 << i))
+            r |= (1 << (7 - i));
+    }
+    return r;
+}
+
+static int ftgmac100_mcast_hash (ftgmac100_state *s, const uint8_t *data)
+{
+#define CRCPOLY_BE    0x04c11db7
+    int i, len;
+    uint32_t crc = 0xFFFFFFFF;
+
+    /* 
+     * 2011.12.28 
+     * It's a FTGMAC100 hardware bug reported by MTD Jeffrey & Jason
+     */
+    if (s->maccr & MACCR_GMODE)
+        len = 5;
+    else
+        len = 6;
+ 
+    while (len--) {
+        uint32_t c = *(data++);
+        for (i = 0; i < 8; ++i) {
+            crc = (crc << 1)^ ((((crc>>31)^c)&0x01) ? CRCPOLY_BE : 0);
+            c >>= 1;
+        }
+    }
+    crc = ~crc;
+ 
+    /* Reverse CRC32 and return MSB 6 bits only */
+    return bitrev8(crc >> 24) >> 2;
+}
+
+static inline void ftgmac100_update_irq(ftgmac100_state *s)
+{
+    if (s->isr & s->ier)
+        qemu_set_irq(s->irq, 1);
+    else
+        qemu_set_irq(s->irq, 0);
+}
+
+static int ftgmac100_can_receive(NetClientState *nc)
+{
+    ftgmac100_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    ftgmac100_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;
+
+    cpu_physical_memory_read(off, (uint8_t *)&rxd, sizeof(rxd));
+
+    return !rxd.owner;
+}
+
+static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, 
size_t size)
+{
+    const uint8_t *ptr = buf;
+    hwaddr off;
+    size_t len;
+    ftgmac100_rxdesc_t rxd;
+    ftgmac100_state *s = 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)) {
+            printf("[qemu] ftgmac100_receive: bcst filtered\n");
+            return -1;
+        }
+    } else {
+        bcst = 0;
+    }
+
+    /* if it's a multicast */
+    if ((buf[0] == 0x01) && (buf[1] == 0x00) && (buf[2] == 0x5e) 
+        && (buf[3] <= 0x7f)) {
+        mcst = 1;
+        if (!(s->maccr & MACCR_RCV_ALL) && !(s->maccr & MACCR_RX_MULTIPKT)) {
+            int hash;
+            if (!(s->maccr & MACCR_HT_MULTI_EN)) {
+                printf("[qemu] ftgmac100_receive: mcst filtered\n");
+                return -1;
+            }
+            hash = ftgmac100_mcast_hash(s, buf);
+            if (!(s->mhash[hash / 32] & (1 << (hash % 32)))) {
+                printf("[qemu] ftgmac100_receive: mcst filtered\n");
+                return -1;
+            }
+        }
+    } else {
+        mcst = 0;
+    }
+
+    /* check if the destination matches NIC mac address */
+    if (!(s->maccr & MACCR_RCV_ALL) && !bcst && !mcst) {
+        if (memcmp(s->conf.macaddr.a, buf, 6)) {
+#if 0
+            printf("[qemu] ftgmac100_receive: pkt filtered\n");
+            printf("[qemu] packet dump: (IF 
MAC=%02X:%02X:%02X:%02X:%02X:%02X)\n",
+                s->conf.macaddr.a[0], s->conf.macaddr.a[1],
+                s->conf.macaddr.a[2], s->conf.macaddr.a[3],
+                s->conf.macaddr.a[4], s->conf.macaddr.a[5]);
+            for (off = 0; off < 14; ++off) {
+                printf("%02X ", buf[off]);
+            }
+            printf("\n");
+#endif
+            return -1;
+        }
+    }
+
+    while (size > 0) {
+        off = s->rx_bar + s->rx_idx * sizeof(rxd);
+        cpu_physical_memory_read(off, (uint8_t *)&rxd, sizeof(rxd));
+        if (rxd.owner) {
+            s->isr |= ISR_NORXBUF;
+            printf("[qemu] ftgmac100: out of rxd!? (ptr=%p, buf=%p)\n", ptr, 
buf);
+            return -1;
+        }
+
+        if (ptr == buf)
+            rxd.frs = 1;
+        else
+            rxd.frs = 0;
+        
+        len = size > rxd.len ? rxd.len : size;
+        cpu_physical_memory_write(rxd.buf, (uint8_t *)ptr, len);
+        ptr  += len;
+        size -= len;
+
+        if (size <= 0)
+            rxd.lrs = 1;
+        else
+            rxd.lrs = 0;
+
+        rxd.len = len;
+        rxd.bcast = bcst;
+        rxd.mcast = mcst;
+        rxd.owner = 1;
+        
+        /* write-back the rx descriptor */
+        cpu_physical_memory_write(off, (uint8_t *)&rxd, sizeof(rxd));
+
+        if (rxd.end)
+            s->rx_idx = 0;
+        else
+            s->rx_idx += 1;
+    }
+    
+    /* 3. update interrupt signal */
+    s->isr |= ISR_RPKT_OK | ISR_RPKT_FINISH;
+    ftgmac100_update_irq(s);
+    
+    return (ssize_t)((uint32_t)ptr - (uint32_t)buf);
+}
+
+static void ftgmac100_transmit(ftgmac100_state *s, uint32_t *bar, uint32_t 
*idx)
+{
+    hwaddr off;
+    uint8_t *buf;
+    ftgmac100_txdesc_t txd;
+    
+    if ((s->maccr & (MACCR_XMT_EN | MACCR_XDMA_EN)) != (MACCR_XMT_EN | 
MACCR_XDMA_EN))
+        return;
+    
+    do {
+        off = (*bar) + (*idx) * sizeof(txd);
+        cpu_physical_memory_read(off, (uint8_t *)&txd, sizeof(txd));
+        if (!txd.owner) {
+            s->isr |= ISR_NOTXBUF;
+            break;
+        }
+        if (txd.fts)
+            s->txbuff.len = 0;
+        buf = s->txbuff.buf + s->txbuff.len;
+        cpu_physical_memory_read(txd.buf, (uint8_t *)buf, txd.len);
+        s->txbuff.len += txd.len;
+        if (txd.lts) {
+            if (s->maccr & MACCR_LOOP_EN) {
+                ftgmac100_receive(&s->nic->nc, s->txbuff.buf, s->txbuff.len);
+            } else {
+                qemu_send_packet(&s->nic->nc, s->txbuff.buf, s->txbuff.len);
+            }
+        }
+        if (txd.end)
+            *idx = 0;
+        else
+            *idx += 1;
+        if (txd.tx2fic)
+            s->isr |= ISR_XPKT_OK;
+        if (txd.txic)
+            s->isr |= ISR_XPKT_FINISH;
+
+        txd.owner = 0;
+        cpu_physical_memory_write(off, (uint8_t *)&txd, sizeof(txd));
+    } while(1);
+}
+
+static void ftgmac100_timer_tick(void *opaque)
+{
+    ftgmac100_state *s = opaque;
+    
+    /* 1. process high priority tx ring */
+    if (s->hptx_bar && (s->maccr & MACCR_HPTXR_EN)) {
+        ftgmac100_transmit(s, &s->hptx_bar, &s->hptx_idx);
+    }
+
+    /* 2. process normal priority tx ring */
+    if (s->tx_bar) {
+        ftgmac100_transmit(s, &s->tx_bar, &s->tx_idx);
+    }
+
+    /* 3. update interrupt signal */
+    ftgmac100_update_irq(s);
+}
+
+static uint64_t ftgmac100_mem_read(void *opaque, hwaddr addr, unsigned int 
size)
+{
+    ftgmac100_state *s = opaque;
+    uint32_t rc = 0;
+
+    switch (addr) {
+    case REG_ISR:
+        return s->isr;
+    case REG_IMR:
+        return s->ier;
+    case REG_HMAC:
+        return s->conf.macaddr.a[1] 
+               | (s->conf.macaddr.a[0] << 8);
+    case REG_LMAC:
+        return s->conf.macaddr.a[5] 
+               | (s->conf.macaddr.a[4] << 8) 
+               | (s->conf.macaddr.a[3] << 16) 
+               | (s->conf.macaddr.a[2] << 24);
+    case REG_MHASH0:
+        return s->mhash[0];
+    case REG_MHASH1:
+        return s->mhash[1];
+    case REG_TXBAR:
+        return s->tx_bar;
+    case REG_RXBAR:
+        return s->rx_bar;
+    case REG_HPTXBAR:
+        return s->hptx_bar;
+    case REG_ITC:
+        return 0x00000000;
+    case REG_APTC:
+        return 0x00000001;
+    case REG_DBLAC:
+        return 0x00022f72;
+    case 0x3c:
+        return 0x0c000000;
+    case 0x40:
+        return 0x00000600;
+    case 0x44:
+        return 0x0000001b;
+    case 0x48:
+        return 0x000000f1;
+    case 0x4c:
+        return 0x00000640;
+    case REG_MACCR:
+        return s->maccr;
+    case REG_MACSR:
+        return s->macsr;
+    case REG_PHYCTRL:
+        return s->phycr;
+    case REG_PHYDATA:
+        do {
+            uint8_t dev = (s->phycr >> 16) & 0x1f;
+            uint8_t reg = (s->phycr >> 21) & 0x1f;
+            if (dev != 0)
+                break;
+            if (s->phycr_rd) {
+                switch(reg) {
+                case 0:    /* PHY control register */
+                    return 0x1140 << 16;
+                case 1:    /* PHY status register */
+                    return 0x796d << 16;
+                case 2:    /* PHY ID 1 register */
+                    return 0x0141 << 16;
+                case 3:    /* PHY ID 2 register */
+                    return 0x0cc2 << 16;
+                case 4:    /* Autonegotiation advertisement register */
+                    return 0x0de1 << 16;
+                case 5:    /* Autonegotiation partner abilities register */
+                    return 0x45e1 << 16;
+                case 17:/* Marvell 88E1111: PHY Specific Status Register - 
Copper */
+                    return ((2 << 14) | (1 << 13) | (1 << 11) | (1 << 10)) << 
16;
+                }
+            }
+        } while(0);
+        break;
+    case REG_FCR:
+        return (2 << 9);
+    case REG_BPR:
+        return (4 << 8);
+    case REG_TXPTR:
+        return s->tx_idx;
+    case REG_HPTXPTR:
+        return s->hptx_idx;
+    case REG_RXPTR:
+        return s->rx_idx;
+    case REG_TXPKT:
+        return s->tx_pkt;
+    case REG_RXPKT:
+        return s->rx_pkt;
+    case REG_RXBCST:
+        return s->rx_bcst;
+    case REG_RXMCST:
+        return s->rx_mcst;
+    case REG_RXRUNT:
+        return s->rx_runt;
+    case REG_RXERR0:
+        return (s->rx_crc << 16) | (s->rx_ftl);
+    case REG_RXERR1:
+        return (s->rx_drop << 16);
+    default:
+        break;
+    }
+
+    return rc;
+}
+
+static void ftgmac100_chip_reset(ftgmac100_state *s)
+{
+    s->isr = 0;
+    s->ier = 0;
+    s->mhash[0] = 0;
+    s->mhash[1] = 0;
+    s->tx_bar = 0;
+    s->rx_bar = 0;
+    s->hptx_bar = 0;
+    s->tx_idx = 0;
+    s->rx_idx = 0;
+    s->hptx_idx = 0;
+    s->maccr = 0;
+    s->macsr = 0;
+    s->phycr = 0;
+    s->txbuff.len = 0;
+    s->rx_pkt = 0;
+    s->rx_bcst = 0;
+    s->rx_mcst = 0;
+    s->rx_runt = 0;
+    s->rx_drop = 0;
+    s->rx_crc = 0;
+    s->rx_ftl = 0;
+    s->tx_pkt = 0;
+    
+    if (s->qtimer)
+        qemu_del_timer(s->qtimer);
+
+    ftgmac100_update_irq(s);
+}
+
+static void ftgmac100_mem_write(void *opaque, hwaddr addr, uint64_t val, 
unsigned int size)
+{
+    ftgmac100_state *s = opaque;
+    
+    switch (addr) {
+    case REG_ISR:
+        s->isr &= ~((uint32_t)val);
+        ftgmac100_update_irq(s);
+        break;
+    case REG_IMR:
+        s->ier = (uint32_t)val;
+        ftgmac100_update_irq(s);
+        break;
+    case REG_HMAC:
+        s->conf.macaddr.a[1] = (val >> 0) & 0xff;
+        s->conf.macaddr.a[0] = (val >> 8) & 0xff;
+        break;
+    case REG_LMAC:
+        s->conf.macaddr.a[5] = (val >> 0) & 0xff;
+        s->conf.macaddr.a[4] = (val >> 8) & 0xff;
+        s->conf.macaddr.a[3] = (val >> 16) & 0xff;
+        s->conf.macaddr.a[2] = (val >> 24) & 0xff;
+        break;
+    case REG_MHASH0:
+        s->mhash[0] = (uint32_t)val;
+        break;
+    case REG_MHASH1:
+        s->mhash[1] = (uint32_t)val;
+        break;
+    case REG_TXBAR:
+        s->tx_bar = (uint32_t)val;
+        break;
+    case REG_RXBAR:
+        s->rx_bar = (uint32_t)val;
+        break;
+    case REG_HPTXBAR:
+        s->hptx_bar = (uint32_t)val;
+        break;
+    case REG_MACCR:
+        s->maccr = (uint32_t)val;
+        if (s->maccr & MACCR_SW_RST) {
+            ftgmac100_chip_reset(s);
+            s->maccr &= ~MACCR_SW_RST;
+        }
+        break;
+    case REG_MACSR:
+        s->macsr &= ~((uint32_t)val);
+        break;
+    case REG_PHYCTRL:
+        s->phycr = (uint32_t)val;
+        if (s->phycr & PHYCR_MDIORD)
+            s->phycr_rd = 1;
+        else
+            s->phycr_rd = 0;
+        s->phycr &= ~(PHYCR_MDIOWR | PHYCR_MDIORD);
+        break;
+    case REG_TXPD:
+    case REG_HPTXPD:
+        qemu_mod_timer(s->qtimer, qemu_get_clock_ns(vm_clock) + 1);
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps bus_ops = {
+    .read  = ftgmac100_mem_read,
+    .write = ftgmac100_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void ftgmac100_cleanup(NetClientState *nc)
+{
+    ftgmac100_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    s->nic = NULL;
+}
+
+static NetClientInfo net_ftgmac100_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_NIC,
+    .size = sizeof(NICState),
+    .can_receive = ftgmac100_can_receive,
+    .receive = ftgmac100_receive,
+    .cleanup = ftgmac100_cleanup,
+};
+
+static void ftgmac100_reset(DeviceState *dev)
+{
+    ftgmac100_state *s = FROM_SYSBUS(ftgmac100_state, sysbus_from_qdev(dev));
+    
+    ftgmac100_chip_reset(s);
+}
+
+static int ftgmac100_init1(SysBusDevice *dev)
+{
+    ftgmac100_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->mmio, &bus_ops, s, "ftgmac100", 0x1000);
+    sysbus_init_mmio(dev, &s->mmio);
+    sysbus_init_irq(dev, &s->irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
+                          object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+    
+    s->qtimer = qemu_new_timer_ns(vm_clock, ftgmac100_timer_tick, s);
+    
+    ftgmac100_chip_reset(s);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_ftgmac100 = {
+    .name = "ftgmac100",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ier, ftgmac100_state),
+        VMSTATE_UINT32(tx_bar, ftgmac100_state),
+        VMSTATE_UINT32(rx_bar, ftgmac100_state),
+        VMSTATE_UINT32(hptx_bar, ftgmac100_state),
+        VMSTATE_UINT32(tx_idx, ftgmac100_state),
+        VMSTATE_UINT32(rx_idx, ftgmac100_state),
+        VMSTATE_UINT32(hptx_idx, ftgmac100_state),
+        VMSTATE_UINT32(maccr, ftgmac100_state),
+        VMSTATE_UINT32(macsr, ftgmac100_state),
+        VMSTATE_UINT32(phycr, ftgmac100_state),
+        VMSTATE_UINT32_ARRAY(mhash, ftgmac100_state, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property ftgmac100_properties[] = {
+    DEFINE_NIC_PROPERTIES(ftgmac100_state, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ftgmac100_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ftgmac100_init1;
+    dc->reset = ftgmac100_reset;
+    dc->vmsd = &vmstate_ftgmac100;
+    dc->props = ftgmac100_properties;
+}
+
+static TypeInfo ftgmac100_info = {
+    .name           = "ftgmac100",
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(ftgmac100_state),
+    .class_init     = ftgmac100_class_init,
+};
+
+static void ftgmac100_register_types(void)
+{
+    type_register_static(&ftgmac100_info);
+}
+
+/* Legacy helper function.  Should go away when machine config files are
+   implemented.  */
+void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
+void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    qemu_check_nic_model(nd, "ftgmac100");
+    dev = qdev_create(NULL, "ftgmac100");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+    s = sysbus_from_qdev(dev);
+    sysbus_mmio_map(s, 0, base);
+    sysbus_connect_irq(s, 0, irq);
+}
+
+type_init(ftgmac100_register_types)
diff --git a/hw/ftgmac100.h b/hw/ftgmac100.h
new file mode 100644
index 0000000..c8c00f9
--- /dev/null
+++ b/hw/ftgmac100.h
@@ -0,0 +1,191 @@
+/*
+ *
+ * Copyright (C) 2011 Dante Su <address@hidden>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _FTGMAC100_H
+#define _FTGMAC100_H
+
+// --------------------------------------------------------------------
+//        FTGMAC100 MAC Registers
+// --------------------------------------------------------------------
+
+#define REG_ISR             0x00            // interrups status register
+#define REG_IMR             0x04            // interrupt maks register
+#define REG_HMAC            0x08            // MAC address (Most significant)
+#define REG_LMAC            0x0c            // MAC address (Least significant)
+#define REG_MHASH0          0x10            // Multicast Address Hash Table 0 
register
+#define REG_MHASH1          0x14            // Multicast Address Hash Table 1 
register
+#define REG_TXPD            0x18            // Transmit Poll Demand register
+#define REG_RXPD            0x1c            // Receive Poll Demand register
+#define REG_TXBAR           0x20            // Transmit Ring Base Address 
register
+#define REG_RXBAR           0x24            // Receive Ring Base Address 
register
+#define REG_HPTXPD          0x28            // High Priority Transmit Ring 
Base Address register
+#define REG_HPTXBAR         0x2C            // High Priority Receive Ring Base 
Address register
+#define REG_ITC             0x30            // interrupt timer control register
+#define REG_APTC            0x34            // Automatic Polling Timer control 
register
+#define REG_DBLAC           0x38            // DMA Burst Length and 
Arbitration control register
+
+#define REG_MACCR           0x50            // MAC control register
+#define REG_MACSR           0x54            // MAC status register
+#define REG_TSTMODE         0x58            // test mode register
+#define REG_PHYCTRL         0x60            // PHY control register
+#define REG_PHYDATA         0x64            // PHY Write Data register
+#define REG_FCR             0x68            // Flow Control register
+#define REG_BPR             0x6c            // back pressure register
+#define REG_WOLCR           0x70            // Wake-On-Lan control register
+#define REG_WOLSR           0x74            // Wake-On-Lan status register
+#define REG_WFCRC           0x78            // Wake-up Frame CRC register
+#define REG_WFBM1           0x80            // wake-up frame byte mask 1st 
double word register
+#define REG_WFBM2           0x84            // wake-up frame byte mask 2nd 
double word register
+#define REG_WFBM3           0x88            // wake-up frame byte mask 3rd 
double word register
+#define REG_WFBM4           0x8c            // wake-up frame byte mask 4th 
double word register
+#define REG_TXPTR           0x90
+#define REG_HPTXPTR         0x94
+#define REG_RXPTR           0x98
+#define REG_TXPKT           0xa0
+#define REG_TXERR0          0xa4
+#define REG_TXERR1          0xa8
+#define REG_TXERR2          0xac
+#define REG_RXPKT           0xb0
+#define REG_RXBCST          0xb4
+#define REG_RXMCST          0xb8
+#define REG_RXRUNT          0xc0
+#define REG_RXERR0          0xc4
+#define REG_RXERR1          0xc8
+
+//Interrupt status register(ISR), Interrupt mask register(IMR) bit setting
+#define ISR_NOHTXB            (1UL<<10)
+#define ISR_PHYSTS_CHG        (1UL<<9)
+#define ISR_AHB_ERR            (1UL<<8)
+#define ISR_XPKT_LOST        (1UL<<7)
+#define ISR_NOTXBUF            (1UL<<6)
+#define ISR_XPKT_OK            (1UL<<5)        // FIFO
+#define ISR_XPKT_FINISH        (1UL<<4)        // ETHER
+#define ISR_RPKT_LOST        (1UL<<3)
+#define ISR_NORXBUF            (1UL<<2)
+#define ISR_RPKT_OK            (1UL<<1)        // FIFO
+#define ISR_RPKT_FINISH        (1UL<<0)        // ETHER
+
+/* MACC control bits */
+#define MACCR_SW_RST            (1UL<<31)
+#define MACCR_100M                (1UL<<19)
+#define MACCR_CRC_DIS            (1UL<<18)
+#define MACCR_RX_BROADPKT        (1UL<<17)
+#define MACCR_RX_MULTIPKT        (1UL<<16)
+#define MACCR_HT_MULTI_EN        (1UL<<15)
+#define MACCR_RCV_ALL            (1UL<<14)
+#define MACCR_JUMBO_LF            (1UL<<13)
+#define MACCR_RX_RUNT            (1UL<<12)
+#define MACCR_CRC_APD            (1UL<<10)
+#define MACCR_GMODE                (1UL<<9)
+#define MACCR_FULLDUP            (1UL<<8)
+#define MACCR_ENRX_IN_HALFTX    (1UL<<7)
+#define MACCR_LOOP_EN            (1UL<<6)
+#define MACCR_HPTXR_EN            (1UL<<5)
+#define MACCR_VLAN_RM            (1UL<<4)
+#define MACCR_RCV_EN            (1UL<<3)
+#define MACCR_XMT_EN            (1UL<<2)
+#define MACCR_RDMA_EN            (1UL<<1)
+#define MACCR_XDMA_EN            (1UL<<0)
+
+// --------------------------------------------------------------------
+//        MII PHY Registers
+// --------------------------------------------------------------------
+
+//
+// Bits related to the MII interface
+//
+#define PHYCR_MDIOWR            (1 << 27)
+#define PHYCR_MDIORD            (1 << 26)
+
+// --------------------------------------------------------------------
+//        Receive Ring descriptor structure
+// --------------------------------------------------------------------
+typedef struct {
+    // RXDES0
+    uint32_t len: 14; // 0~13
+    uint32_t rsvd1: 1; // 14
+    uint32_t end: 1; //15
+    uint32_t mcast: 1; //16
+    uint32_t bcast: 1; //17
+    uint32_t rxerr: 1; //18
+    uint32_t crcerr: 1; //19
+    uint32_t ftl: 1; //20
+    uint32_t runt: 1; //21
+    uint32_t oddnb: 1; //22
+    uint32_t fifofull: 1; //23
+    uint32_t pauseopc: 1; //24
+    uint32_t pausefrm: 1; //25
+    uint32_t rsvd2: 2; //26 ~ 27
+    uint32_t lrs: 1; //28
+    uint32_t frs: 1; //29
+    uint32_t rsvd3: 1; //30
+    uint32_t owner: 1; //31 - 1:Software, 0: Hardware
+
+    // RXDES1
+    uint32_t vlantag: 16; // 0 ~ 15
+    uint32_t rsvd4: 4; // 16 ~ 19
+    uint32_t proto: 2; // 20 ~ 21
+    uint32_t llc: 1; // 22
+    uint32_t df: 1; // 23
+    uint32_t vlan: 1; // 24
+    uint32_t tcpcs: 1; // 25
+    uint32_t udpcs: 1; // 26
+    uint32_t ipcs: 1; // 27
+    uint32_t rsvd5: 4; // 28 ~ 31
+
+    // RXDES2
+    void    *skb;
+
+    // RXDES3
+    uint32_t buf;
+} ftgmac100_rxdesc_t;
+
+typedef struct {
+    // TXDES0
+    uint32_t len: 14;
+    uint32_t rsvd1: 1;
+    uint32_t end: 1;
+    uint32_t rsvd2: 3;
+    uint32_t crcerr: 1;
+    uint32_t rsvd3: 8;
+    uint32_t lts: 1;
+    uint32_t fts: 1;
+    uint32_t rsvd4: 1;
+    uint32_t owner: 1; // 31 - 1:Hardware, 0: Software
+
+    // TXDES1
+    uint32_t vlantag: 16;
+    uint32_t vlan:   1;
+    uint32_t tcpcs:  1;
+    uint32_t udpcs:  1;
+    uint32_t ipcs:   1;
+    uint32_t rsvd5:  2;
+    uint32_t llc:    1;
+    uint32_t rsvd6:  7;
+    uint32_t tx2fic: 1;
+    uint32_t txic:   1;
+
+    // TXDES2
+    void    *skb;
+
+    // TXDES3
+    uint32_t buf;
+} ftgmac100_txdesc_t;
+
+#endif    /* #ifndef _FTGMAC100_H */
-- 
1.7.9.5


********************* Confidentiality Notice ************************
This electronic message and any attachments may contain
confidential and legally privileged information or
information which is otherwise protected from disclosure.
If you are not the intended recipient,please do not disclose
the contents, either in whole or in part, to anyone,and
immediately delete the message and any attachments from
your computer system and destroy all hard copies.
Thank you for your cooperation.
***********************************************************************




reply via email to

[Prev in Thread] Current Thread [Next in Thread]