Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com> --- 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 <dant...@faraday-tech.com> + * + * 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 <dant...@faraday-tech.com> + * + * 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. ***********************************************************************