ns_gige.cc revision 2846
16019Shines@cs.fsu.edu/*
26019Shines@cs.fsu.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
37178Sgblack@eecs.umich.edu * All rights reserved.
47178Sgblack@eecs.umich.edu *
57178Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67178Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77178Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97178Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117178Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127178Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137178Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147178Sgblack@eecs.umich.edu * this software without specific prior written permission.
156019Shines@cs.fsu.edu *
166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * Authors: Nathan Binkert
296019Shines@cs.fsu.edu *          Lisa Hsu
306019Shines@cs.fsu.edu */
316019Shines@cs.fsu.edu
326019Shines@cs.fsu.edu/** @file
336019Shines@cs.fsu.edu * Device module for modelling the National Semiconductor
346019Shines@cs.fsu.edu * DP83820 ethernet controller.  Does not support priority queueing
356019Shines@cs.fsu.edu */
366019Shines@cs.fsu.edu#include <deque>
376019Shines@cs.fsu.edu#include <string>
386019Shines@cs.fsu.edu
396019Shines@cs.fsu.edu#include "arch/alpha/ev5.hh"
406019Shines@cs.fsu.edu#include "base/inet.hh"
416019Shines@cs.fsu.edu#include "cpu/thread_context.hh"
426019Shines@cs.fsu.edu#include "dev/etherlink.hh"
436019Shines@cs.fsu.edu#include "dev/ns_gige.hh"
446019Shines@cs.fsu.edu#include "dev/pciconfigall.hh"
456019Shines@cs.fsu.edu#include "mem/packet.hh"
466019Shines@cs.fsu.edu#include "sim/builder.hh"
476019Shines@cs.fsu.edu#include "sim/debug.hh"
487639Sgblack@eecs.umich.edu#include "sim/host.hh"
497639Sgblack@eecs.umich.edu#include "sim/stats.hh"
507639Sgblack@eecs.umich.edu#include "sim/system.hh"
517639Sgblack@eecs.umich.edu
527639Sgblack@eecs.umich.educonst char *NsRxStateStrings[] =
537639Sgblack@eecs.umich.edu{
547639Sgblack@eecs.umich.edu    "rxIdle",
557639Sgblack@eecs.umich.edu    "rxDescRefr",
567639Sgblack@eecs.umich.edu    "rxDescRead",
577639Sgblack@eecs.umich.edu    "rxFifoBlock",
587639Sgblack@eecs.umich.edu    "rxFragWrite",
597639Sgblack@eecs.umich.edu    "rxDescWrite",
607639Sgblack@eecs.umich.edu    "rxAdvance"
617639Sgblack@eecs.umich.edu};
627639Sgblack@eecs.umich.edu
637639Sgblack@eecs.umich.educonst char *NsTxStateStrings[] =
647639Sgblack@eecs.umich.edu{
657639Sgblack@eecs.umich.edu    "txIdle",
667639Sgblack@eecs.umich.edu    "txDescRefr",
677639Sgblack@eecs.umich.edu    "txDescRead",
687639Sgblack@eecs.umich.edu    "txFifoBlock",
697639Sgblack@eecs.umich.edu    "txFragRead",
707639Sgblack@eecs.umich.edu    "txDescWrite",
717639Sgblack@eecs.umich.edu    "txAdvance"
727639Sgblack@eecs.umich.edu};
737639Sgblack@eecs.umich.edu
747639Sgblack@eecs.umich.educonst char *NsDmaState[] =
757639Sgblack@eecs.umich.edu{
767639Sgblack@eecs.umich.edu    "dmaIdle",
777639Sgblack@eecs.umich.edu    "dmaReading",
787639Sgblack@eecs.umich.edu    "dmaWriting",
797639Sgblack@eecs.umich.edu    "dmaReadWaiting",
807639Sgblack@eecs.umich.edu    "dmaWriteWaiting"
817639Sgblack@eecs.umich.edu};
827639Sgblack@eecs.umich.edu
837639Sgblack@eecs.umich.eduusing namespace std;
847639Sgblack@eecs.umich.eduusing namespace Net;
857639Sgblack@eecs.umich.eduusing namespace TheISA;
867639Sgblack@eecs.umich.edu
877639Sgblack@eecs.umich.edu///////////////////////////////////////////////////////////////////////
887639Sgblack@eecs.umich.edu//
897639Sgblack@eecs.umich.edu// NSGigE PCI Device
907639Sgblack@eecs.umich.edu//
917639Sgblack@eecs.umich.eduNSGigE::NSGigE(Params *p)
927639Sgblack@eecs.umich.edu    : PciDev(p), ioEnable(false),
937639Sgblack@eecs.umich.edu      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
947356Sgblack@eecs.umich.edu      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
957356Sgblack@eecs.umich.edu      txXferLen(0), rxXferLen(0), clock(p->clock),
967356Sgblack@eecs.umich.edu      txState(txIdle), txEnable(false), CTDD(false),
977435Sgblack@eecs.umich.edu      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
987435Sgblack@eecs.umich.edu      rxEnable(false), CRDD(false), rxPktBytes(0),
997435Sgblack@eecs.umich.edu      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
1007435Sgblack@eecs.umich.edu      eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this),
1017435Sgblack@eecs.umich.edu      txDmaReadEvent(this), txDmaWriteEvent(this),
1027435Sgblack@eecs.umich.edu      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
1037435Sgblack@eecs.umich.edu      txDelay(p->tx_delay), rxDelay(p->rx_delay),
1047435Sgblack@eecs.umich.edu      rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
1057435Sgblack@eecs.umich.edu      txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
1067435Sgblack@eecs.umich.edu      acceptMulticast(false), acceptUnicast(false),
1077435Sgblack@eecs.umich.edu      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
1087639Sgblack@eecs.umich.edu      intrTick(0), cpuPendingIntr(false),
1097639Sgblack@eecs.umich.edu      intrEvent(0), interface(0)
1107639Sgblack@eecs.umich.edu{
1117435Sgblack@eecs.umich.edu
1127639Sgblack@eecs.umich.edu    intrDelay = p->intr_delay;
1137639Sgblack@eecs.umich.edu    dmaReadDelay = p->dma_read_delay;
1147639Sgblack@eecs.umich.edu    dmaWriteDelay = p->dma_write_delay;
1157639Sgblack@eecs.umich.edu    dmaReadFactor = p->dma_read_factor;
1167639Sgblack@eecs.umich.edu    dmaWriteFactor = p->dma_write_factor;
1177639Sgblack@eecs.umich.edu
1187639Sgblack@eecs.umich.edu    regsReset();
1197639Sgblack@eecs.umich.edu    memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
1207639Sgblack@eecs.umich.edu
1217639Sgblack@eecs.umich.edu    memset(&rxDesc32, 0, sizeof(rxDesc32));
1227639Sgblack@eecs.umich.edu    memset(&txDesc32, 0, sizeof(txDesc32));
1237639Sgblack@eecs.umich.edu    memset(&rxDesc64, 0, sizeof(rxDesc64));
1247639Sgblack@eecs.umich.edu    memset(&txDesc64, 0, sizeof(txDesc64));
1257639Sgblack@eecs.umich.edu}
1267639Sgblack@eecs.umich.edu
1277639Sgblack@eecs.umich.eduNSGigE::~NSGigE()
1287639Sgblack@eecs.umich.edu{}
1297639Sgblack@eecs.umich.edu
1307639Sgblack@eecs.umich.eduvoid
1317639Sgblack@eecs.umich.eduNSGigE::regStats()
1327639Sgblack@eecs.umich.edu{
1337639Sgblack@eecs.umich.edu    txBytes
1347639Sgblack@eecs.umich.edu        .name(name() + ".txBytes")
1357639Sgblack@eecs.umich.edu        .desc("Bytes Transmitted")
1367639Sgblack@eecs.umich.edu        .prereq(txBytes)
1377639Sgblack@eecs.umich.edu        ;
1387639Sgblack@eecs.umich.edu
1397639Sgblack@eecs.umich.edu    rxBytes
1407639Sgblack@eecs.umich.edu        .name(name() + ".rxBytes")
1417639Sgblack@eecs.umich.edu        .desc("Bytes Received")
1427639Sgblack@eecs.umich.edu        .prereq(rxBytes)
1437639Sgblack@eecs.umich.edu        ;
1447639Sgblack@eecs.umich.edu
1457639Sgblack@eecs.umich.edu    txPackets
1468144SAli.Saidi@ARM.com        .name(name() + ".txPackets")
1477639Sgblack@eecs.umich.edu        .desc("Number of Packets Transmitted")
1487639Sgblack@eecs.umich.edu        .prereq(txBytes)
1497639Sgblack@eecs.umich.edu        ;
1507639Sgblack@eecs.umich.edu
1517639Sgblack@eecs.umich.edu    rxPackets
1527639Sgblack@eecs.umich.edu        .name(name() + ".rxPackets")
1537639Sgblack@eecs.umich.edu        .desc("Number of Packets Received")
1547639Sgblack@eecs.umich.edu        .prereq(rxBytes)
1557639Sgblack@eecs.umich.edu        ;
1567639Sgblack@eecs.umich.edu
1577639Sgblack@eecs.umich.edu    txIpChecksums
1587639Sgblack@eecs.umich.edu        .name(name() + ".txIpChecksums")
1597639Sgblack@eecs.umich.edu        .desc("Number of tx IP Checksums done by device")
1607639Sgblack@eecs.umich.edu        .precision(0)
1617639Sgblack@eecs.umich.edu        .prereq(txBytes)
1627639Sgblack@eecs.umich.edu        ;
1637639Sgblack@eecs.umich.edu
1647639Sgblack@eecs.umich.edu    rxIpChecksums
1657639Sgblack@eecs.umich.edu        .name(name() + ".rxIpChecksums")
1667639Sgblack@eecs.umich.edu        .desc("Number of rx IP Checksums done by device")
1677639Sgblack@eecs.umich.edu        .precision(0)
1687639Sgblack@eecs.umich.edu        .prereq(rxBytes)
1697639Sgblack@eecs.umich.edu        ;
1707639Sgblack@eecs.umich.edu
1717639Sgblack@eecs.umich.edu    txTcpChecksums
1727639Sgblack@eecs.umich.edu        .name(name() + ".txTcpChecksums")
1737639Sgblack@eecs.umich.edu        .desc("Number of tx TCP Checksums done by device")
1747639Sgblack@eecs.umich.edu        .precision(0)
1757639Sgblack@eecs.umich.edu        .prereq(txBytes)
1767639Sgblack@eecs.umich.edu        ;
1777639Sgblack@eecs.umich.edu
1787639Sgblack@eecs.umich.edu    rxTcpChecksums
1797639Sgblack@eecs.umich.edu        .name(name() + ".rxTcpChecksums")
1807639Sgblack@eecs.umich.edu        .desc("Number of rx TCP Checksums done by device")
1817639Sgblack@eecs.umich.edu        .precision(0)
1827639Sgblack@eecs.umich.edu        .prereq(rxBytes)
1837591SAli.Saidi@ARM.com        ;
1847639Sgblack@eecs.umich.edu
1857435Sgblack@eecs.umich.edu    txUdpChecksums
1867435Sgblack@eecs.umich.edu        .name(name() + ".txUdpChecksums")
1877639Sgblack@eecs.umich.edu        .desc("Number of tx UDP Checksums done by device")
1887639Sgblack@eecs.umich.edu        .precision(0)
1897639Sgblack@eecs.umich.edu        .prereq(txBytes)
1907639Sgblack@eecs.umich.edu        ;
1917639Sgblack@eecs.umich.edu
1927639Sgblack@eecs.umich.edu    rxUdpChecksums
1937639Sgblack@eecs.umich.edu        .name(name() + ".rxUdpChecksums")
1947639Sgblack@eecs.umich.edu        .desc("Number of rx UDP Checksums done by device")
1957639Sgblack@eecs.umich.edu        .precision(0)
1967639Sgblack@eecs.umich.edu        .prereq(rxBytes)
1977639Sgblack@eecs.umich.edu        ;
1987639Sgblack@eecs.umich.edu
1997639Sgblack@eecs.umich.edu    descDmaReads
2007639Sgblack@eecs.umich.edu        .name(name() + ".descDMAReads")
2017639Sgblack@eecs.umich.edu        .desc("Number of descriptors the device read w/ DMA")
2027639Sgblack@eecs.umich.edu        .precision(0)
2037639Sgblack@eecs.umich.edu        ;
2047639Sgblack@eecs.umich.edu
2057639Sgblack@eecs.umich.edu    descDmaWrites
2067639Sgblack@eecs.umich.edu        .name(name() + ".descDMAWrites")
2077639Sgblack@eecs.umich.edu        .desc("Number of descriptors the device wrote w/ DMA")
2087639Sgblack@eecs.umich.edu        .precision(0)
2097639Sgblack@eecs.umich.edu        ;
2107639Sgblack@eecs.umich.edu
2117639Sgblack@eecs.umich.edu    descDmaRdBytes
2127639Sgblack@eecs.umich.edu        .name(name() + ".descDmaReadBytes")
2137639Sgblack@eecs.umich.edu        .desc("number of descriptor bytes read w/ DMA")
2147639Sgblack@eecs.umich.edu        .precision(0)
2157639Sgblack@eecs.umich.edu        ;
2167639Sgblack@eecs.umich.edu
2177639Sgblack@eecs.umich.edu   descDmaWrBytes
2187639Sgblack@eecs.umich.edu        .name(name() + ".descDmaWriteBytes")
2197639Sgblack@eecs.umich.edu        .desc("number of descriptor bytes write w/ DMA")
2207639Sgblack@eecs.umich.edu        .precision(0)
2217639Sgblack@eecs.umich.edu        ;
2227639Sgblack@eecs.umich.edu
2237591SAli.Saidi@ARM.com    txBandwidth
2247591SAli.Saidi@ARM.com        .name(name() + ".txBandwidth")
2257639Sgblack@eecs.umich.edu        .desc("Transmit Bandwidth (bits/s)")
2267639Sgblack@eecs.umich.edu        .precision(0)
2277639Sgblack@eecs.umich.edu        .prereq(txBytes)
2287639Sgblack@eecs.umich.edu        ;
2297639Sgblack@eecs.umich.edu
2307639Sgblack@eecs.umich.edu    rxBandwidth
2317639Sgblack@eecs.umich.edu        .name(name() + ".rxBandwidth")
2327639Sgblack@eecs.umich.edu        .desc("Receive Bandwidth (bits/s)")
2337639Sgblack@eecs.umich.edu        .precision(0)
2347639Sgblack@eecs.umich.edu        .prereq(rxBytes)
2357639Sgblack@eecs.umich.edu        ;
2367639Sgblack@eecs.umich.edu
2377639Sgblack@eecs.umich.edu    totBandwidth
2387639Sgblack@eecs.umich.edu        .name(name() + ".totBandwidth")
2397639Sgblack@eecs.umich.edu        .desc("Total Bandwidth (bits/s)")
2407639Sgblack@eecs.umich.edu        .precision(0)
2417639Sgblack@eecs.umich.edu        .prereq(totBytes)
2427639Sgblack@eecs.umich.edu        ;
2437639Sgblack@eecs.umich.edu
2447639Sgblack@eecs.umich.edu    totPackets
2457435Sgblack@eecs.umich.edu        .name(name() + ".totPackets")
2467435Sgblack@eecs.umich.edu        .desc("Total Packets")
2477639Sgblack@eecs.umich.edu        .precision(0)
2487639Sgblack@eecs.umich.edu        .prereq(totBytes)
2497639Sgblack@eecs.umich.edu        ;
2507639Sgblack@eecs.umich.edu
2517639Sgblack@eecs.umich.edu    totBytes
2527639Sgblack@eecs.umich.edu        .name(name() + ".totBytes")
2537639Sgblack@eecs.umich.edu        .desc("Total Bytes")
2547639Sgblack@eecs.umich.edu        .precision(0)
2557639Sgblack@eecs.umich.edu        .prereq(totBytes)
2567639Sgblack@eecs.umich.edu        ;
2577639Sgblack@eecs.umich.edu
2587639Sgblack@eecs.umich.edu    totPacketRate
2597639Sgblack@eecs.umich.edu        .name(name() + ".totPPS")
2607639Sgblack@eecs.umich.edu        .desc("Total Tranmission Rate (packets/s)")
2617639Sgblack@eecs.umich.edu        .precision(0)
2627639Sgblack@eecs.umich.edu        .prereq(totBytes)
2637639Sgblack@eecs.umich.edu        ;
2647639Sgblack@eecs.umich.edu
2657639Sgblack@eecs.umich.edu    txPacketRate
2667639Sgblack@eecs.umich.edu        .name(name() + ".txPPS")
2677639Sgblack@eecs.umich.edu        .desc("Packet Tranmission Rate (packets/s)")
2687639Sgblack@eecs.umich.edu        .precision(0)
2697639Sgblack@eecs.umich.edu        .prereq(txBytes)
2707639Sgblack@eecs.umich.edu        ;
2717639Sgblack@eecs.umich.edu
2727639Sgblack@eecs.umich.edu    rxPacketRate
2737639Sgblack@eecs.umich.edu        .name(name() + ".rxPPS")
2747639Sgblack@eecs.umich.edu        .desc("Packet Reception Rate (packets/s)")
2757639Sgblack@eecs.umich.edu        .precision(0)
2767639Sgblack@eecs.umich.edu        .prereq(rxBytes)
2777639Sgblack@eecs.umich.edu        ;
2787639Sgblack@eecs.umich.edu
2797639Sgblack@eecs.umich.edu    postedSwi
2807639Sgblack@eecs.umich.edu        .name(name() + ".postedSwi")
2817639Sgblack@eecs.umich.edu        .desc("number of software interrupts posted to CPU")
2827639Sgblack@eecs.umich.edu        .precision(0)
2837639Sgblack@eecs.umich.edu        ;
2847639Sgblack@eecs.umich.edu
2857639Sgblack@eecs.umich.edu    totalSwi
2867639Sgblack@eecs.umich.edu        .name(name() + ".totalSwi")
2877639Sgblack@eecs.umich.edu        .desc("total number of Swi written to ISR")
2887639Sgblack@eecs.umich.edu        .precision(0)
2897639Sgblack@eecs.umich.edu        ;
2907639Sgblack@eecs.umich.edu
2917639Sgblack@eecs.umich.edu    coalescedSwi
2927639Sgblack@eecs.umich.edu        .name(name() + ".coalescedSwi")
2937639Sgblack@eecs.umich.edu        .desc("average number of Swi's coalesced into each post")
2947639Sgblack@eecs.umich.edu        .precision(0)
2957639Sgblack@eecs.umich.edu        ;
2967639Sgblack@eecs.umich.edu
2977639Sgblack@eecs.umich.edu    postedRxIdle
2987639Sgblack@eecs.umich.edu        .name(name() + ".postedRxIdle")
2997639Sgblack@eecs.umich.edu        .desc("number of rxIdle interrupts posted to CPU")
3007639Sgblack@eecs.umich.edu        .precision(0)
3017639Sgblack@eecs.umich.edu        ;
3027639Sgblack@eecs.umich.edu
3037639Sgblack@eecs.umich.edu    totalRxIdle
3047639Sgblack@eecs.umich.edu        .name(name() + ".totalRxIdle")
3057639Sgblack@eecs.umich.edu        .desc("total number of RxIdle written to ISR")
3067639Sgblack@eecs.umich.edu        .precision(0)
3077639Sgblack@eecs.umich.edu        ;
3087639Sgblack@eecs.umich.edu
3097639Sgblack@eecs.umich.edu    coalescedRxIdle
3107639Sgblack@eecs.umich.edu        .name(name() + ".coalescedRxIdle")
3117639Sgblack@eecs.umich.edu        .desc("average number of RxIdle's coalesced into each post")
3127639Sgblack@eecs.umich.edu        .precision(0)
3137639Sgblack@eecs.umich.edu        ;
3147639Sgblack@eecs.umich.edu
3157639Sgblack@eecs.umich.edu    postedRxOk
3167639Sgblack@eecs.umich.edu        .name(name() + ".postedRxOk")
3177639Sgblack@eecs.umich.edu        .desc("number of RxOk interrupts posted to CPU")
3187639Sgblack@eecs.umich.edu        .precision(0)
3197639Sgblack@eecs.umich.edu        ;
3207639Sgblack@eecs.umich.edu
3217639Sgblack@eecs.umich.edu    totalRxOk
3227639Sgblack@eecs.umich.edu        .name(name() + ".totalRxOk")
3237435Sgblack@eecs.umich.edu        .desc("total number of RxOk written to ISR")
3247435Sgblack@eecs.umich.edu        .precision(0)
3257639Sgblack@eecs.umich.edu        ;
3267639Sgblack@eecs.umich.edu
3277639Sgblack@eecs.umich.edu    coalescedRxOk
3287591SAli.Saidi@ARM.com        .name(name() + ".coalescedRxOk")
3297639Sgblack@eecs.umich.edu        .desc("average number of RxOk's coalesced into each post")
3307639Sgblack@eecs.umich.edu        .precision(0)
3317435Sgblack@eecs.umich.edu        ;
3327435Sgblack@eecs.umich.edu
3337639Sgblack@eecs.umich.edu    postedRxDesc
3347639Sgblack@eecs.umich.edu        .name(name() + ".postedRxDesc")
3357435Sgblack@eecs.umich.edu        .desc("number of RxDesc interrupts posted to CPU")
3367435Sgblack@eecs.umich.edu        .precision(0)
3377591SAli.Saidi@ARM.com        ;
3387435Sgblack@eecs.umich.edu
3397435Sgblack@eecs.umich.edu    totalRxDesc
3407435Sgblack@eecs.umich.edu        .name(name() + ".totalRxDesc")
3417435Sgblack@eecs.umich.edu        .desc("total number of RxDesc written to ISR")
3427435Sgblack@eecs.umich.edu        .precision(0)
3437435Sgblack@eecs.umich.edu        ;
3447435Sgblack@eecs.umich.edu
3457435Sgblack@eecs.umich.edu    coalescedRxDesc
3467435Sgblack@eecs.umich.edu        .name(name() + ".coalescedRxDesc")
3477435Sgblack@eecs.umich.edu        .desc("average number of RxDesc's coalesced into each post")
3487435Sgblack@eecs.umich.edu        .precision(0)
3497639Sgblack@eecs.umich.edu        ;
3507639Sgblack@eecs.umich.edu
3517639Sgblack@eecs.umich.edu    postedTxOk
3527639Sgblack@eecs.umich.edu        .name(name() + ".postedTxOk")
3537639Sgblack@eecs.umich.edu        .desc("number of TxOk interrupts posted to CPU")
3547639Sgblack@eecs.umich.edu        .precision(0)
3557639Sgblack@eecs.umich.edu        ;
3567639Sgblack@eecs.umich.edu
3577639Sgblack@eecs.umich.edu    totalTxOk
3587639Sgblack@eecs.umich.edu        .name(name() + ".totalTxOk")
3597639Sgblack@eecs.umich.edu        .desc("total number of TxOk written to ISR")
3607639Sgblack@eecs.umich.edu        .precision(0)
3617639Sgblack@eecs.umich.edu        ;
3627435Sgblack@eecs.umich.edu
3637435Sgblack@eecs.umich.edu    coalescedTxOk
3647435Sgblack@eecs.umich.edu        .name(name() + ".coalescedTxOk")
3657639Sgblack@eecs.umich.edu        .desc("average number of TxOk's coalesced into each post")
3667639Sgblack@eecs.umich.edu        .precision(0)
3677639Sgblack@eecs.umich.edu        ;
3687435Sgblack@eecs.umich.edu
3697639Sgblack@eecs.umich.edu    postedTxIdle
3707639Sgblack@eecs.umich.edu        .name(name() + ".postedTxIdle")
3717435Sgblack@eecs.umich.edu        .desc("number of TxIdle interrupts posted to CPU")
3727435Sgblack@eecs.umich.edu        .precision(0)
3737639Sgblack@eecs.umich.edu        ;
3747639Sgblack@eecs.umich.edu
3757639Sgblack@eecs.umich.edu    totalTxIdle
3767639Sgblack@eecs.umich.edu        .name(name() + ".totalTxIdle")
3777435Sgblack@eecs.umich.edu        .desc("total number of TxIdle written to ISR")
3787435Sgblack@eecs.umich.edu        .precision(0)
3797435Sgblack@eecs.umich.edu        ;
3807639Sgblack@eecs.umich.edu
3817639Sgblack@eecs.umich.edu    coalescedTxIdle
3827435Sgblack@eecs.umich.edu        .name(name() + ".coalescedTxIdle")
3837435Sgblack@eecs.umich.edu        .desc("average number of TxIdle's coalesced into each post")
3847435Sgblack@eecs.umich.edu        .precision(0)
3857435Sgblack@eecs.umich.edu        ;
3867639Sgblack@eecs.umich.edu
3877639Sgblack@eecs.umich.edu    postedTxDesc
3887639Sgblack@eecs.umich.edu        .name(name() + ".postedTxDesc")
3897639Sgblack@eecs.umich.edu        .desc("number of TxDesc interrupts posted to CPU")
3907639Sgblack@eecs.umich.edu        .precision(0)
3917435Sgblack@eecs.umich.edu        ;
3927639Sgblack@eecs.umich.edu
3937639Sgblack@eecs.umich.edu    totalTxDesc
3947639Sgblack@eecs.umich.edu        .name(name() + ".totalTxDesc")
3957639Sgblack@eecs.umich.edu        .desc("total number of TxDesc written to ISR")
3967639Sgblack@eecs.umich.edu        .precision(0)
3977435Sgblack@eecs.umich.edu        ;
3987639Sgblack@eecs.umich.edu
3997639Sgblack@eecs.umich.edu    coalescedTxDesc
4007639Sgblack@eecs.umich.edu        .name(name() + ".coalescedTxDesc")
4017639Sgblack@eecs.umich.edu        .desc("average number of TxDesc's coalesced into each post")
4027639Sgblack@eecs.umich.edu        .precision(0)
4037435Sgblack@eecs.umich.edu        ;
4047639Sgblack@eecs.umich.edu
4057639Sgblack@eecs.umich.edu    postedRxOrn
4067639Sgblack@eecs.umich.edu        .name(name() + ".postedRxOrn")
4077639Sgblack@eecs.umich.edu        .desc("number of RxOrn posted to CPU")
4087639Sgblack@eecs.umich.edu        .precision(0)
4097435Sgblack@eecs.umich.edu        ;
4107435Sgblack@eecs.umich.edu
4117435Sgblack@eecs.umich.edu    totalRxOrn
4127435Sgblack@eecs.umich.edu        .name(name() + ".totalRxOrn")
4137639Sgblack@eecs.umich.edu        .desc("total number of RxOrn written to ISR")
4147639Sgblack@eecs.umich.edu        .precision(0)
4157639Sgblack@eecs.umich.edu        ;
4167639Sgblack@eecs.umich.edu
4177639Sgblack@eecs.umich.edu    coalescedRxOrn
4187435Sgblack@eecs.umich.edu        .name(name() + ".coalescedRxOrn")
4197639Sgblack@eecs.umich.edu        .desc("average number of RxOrn's coalesced into each post")
4207639Sgblack@eecs.umich.edu        .precision(0)
4217639Sgblack@eecs.umich.edu        ;
4227639Sgblack@eecs.umich.edu
4237639Sgblack@eecs.umich.edu    coalescedTotal
4247435Sgblack@eecs.umich.edu        .name(name() + ".coalescedTotal")
4257639Sgblack@eecs.umich.edu        .desc("average number of interrupts coalesced into each post")
4267639Sgblack@eecs.umich.edu        .precision(0)
4277639Sgblack@eecs.umich.edu        ;
4287639Sgblack@eecs.umich.edu
4297435Sgblack@eecs.umich.edu    postedInterrupts
4307639Sgblack@eecs.umich.edu        .name(name() + ".postedInterrupts")
4317639Sgblack@eecs.umich.edu        .desc("number of posts to CPU")
4327639Sgblack@eecs.umich.edu        .precision(0)
4337639Sgblack@eecs.umich.edu        ;
4347639Sgblack@eecs.umich.edu
4357639Sgblack@eecs.umich.edu    droppedPackets
4367639Sgblack@eecs.umich.edu        .name(name() + ".droppedPackets")
4377639Sgblack@eecs.umich.edu        .desc("number of packets dropped")
4387639Sgblack@eecs.umich.edu        .precision(0)
4397639Sgblack@eecs.umich.edu        ;
4407435Sgblack@eecs.umich.edu
4417435Sgblack@eecs.umich.edu    coalescedSwi = totalSwi / postedInterrupts;
4427435Sgblack@eecs.umich.edu    coalescedRxIdle = totalRxIdle / postedInterrupts;
4437639Sgblack@eecs.umich.edu    coalescedRxOk = totalRxOk / postedInterrupts;
4447639Sgblack@eecs.umich.edu    coalescedRxDesc = totalRxDesc / postedInterrupts;
4457639Sgblack@eecs.umich.edu    coalescedTxOk = totalTxOk / postedInterrupts;
4467639Sgblack@eecs.umich.edu    coalescedTxIdle = totalTxIdle / postedInterrupts;
4477639Sgblack@eecs.umich.edu    coalescedTxDesc = totalTxDesc / postedInterrupts;
4487639Sgblack@eecs.umich.edu    coalescedRxOrn = totalRxOrn / postedInterrupts;
4497639Sgblack@eecs.umich.edu
4507435Sgblack@eecs.umich.edu    coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc +
4517435Sgblack@eecs.umich.edu                      totalTxOk + totalTxIdle + totalTxDesc +
4527435Sgblack@eecs.umich.edu                      totalRxOrn) / postedInterrupts;
4537435Sgblack@eecs.umich.edu
4547435Sgblack@eecs.umich.edu    txBandwidth = txBytes * Stats::constant(8) / simSeconds;
4557639Sgblack@eecs.umich.edu    rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
4567639Sgblack@eecs.umich.edu    totBandwidth = txBandwidth + rxBandwidth;
4577639Sgblack@eecs.umich.edu    totBytes = txBytes + rxBytes;
4587639Sgblack@eecs.umich.edu    totPackets = txPackets + rxPackets;
4597639Sgblack@eecs.umich.edu
4607639Sgblack@eecs.umich.edu    txPacketRate = txPackets / simSeconds;
4617639Sgblack@eecs.umich.edu    rxPacketRate = rxPackets / simSeconds;
4627435Sgblack@eecs.umich.edu}
4637639Sgblack@eecs.umich.edu
4647639Sgblack@eecs.umich.edu
4657639Sgblack@eecs.umich.edu/**
4667639Sgblack@eecs.umich.edu * This is to write to the PCI general configuration registers
4677435Sgblack@eecs.umich.edu */
4687435Sgblack@eecs.umich.eduTick
4697435Sgblack@eecs.umich.eduNSGigE::writeConfig(Packet *pkt)
4707639Sgblack@eecs.umich.edu{
4717639Sgblack@eecs.umich.edu    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
4727435Sgblack@eecs.umich.edu    if (offset < PCI_DEVICE_SPECIFIC)
4737639Sgblack@eecs.umich.edu        PciDev::writeConfig(pkt);
4747639Sgblack@eecs.umich.edu    else
4757435Sgblack@eecs.umich.edu        panic("Device specific PCI config space not implemented!\n");
4767435Sgblack@eecs.umich.edu
4777435Sgblack@eecs.umich.edu    switch (offset) {
4787639Sgblack@eecs.umich.edu        // seems to work fine without all these PCI settings, but i
4797639Sgblack@eecs.umich.edu        // put in the IO to double check, an assertion will fail if we
4807639Sgblack@eecs.umich.edu        // need to properly implement it
4817639Sgblack@eecs.umich.edu      case PCI_COMMAND:
4827639Sgblack@eecs.umich.edu        if (config.data[offset] & PCI_CMD_IOSE)
4837639Sgblack@eecs.umich.edu            ioEnable = true;
4847639Sgblack@eecs.umich.edu        else
4857435Sgblack@eecs.umich.edu            ioEnable = false;
4867639Sgblack@eecs.umich.edu        break;
4877639Sgblack@eecs.umich.edu    }
4887435Sgblack@eecs.umich.edu    pkt->result = Packet::Success;
4897435Sgblack@eecs.umich.edu    return configDelay;
4907435Sgblack@eecs.umich.edu}
4917639Sgblack@eecs.umich.edu
4927639Sgblack@eecs.umich.edu/**
4937639Sgblack@eecs.umich.edu * This reads the device registers, which are detailed in the NS83820
4947639Sgblack@eecs.umich.edu * spec sheet
4957639Sgblack@eecs.umich.edu */
4967639Sgblack@eecs.umich.eduTick
4977639Sgblack@eecs.umich.eduNSGigE::read(Packet *pkt)
4987435Sgblack@eecs.umich.edu{
4997639Sgblack@eecs.umich.edu    assert(ioEnable);
5007639Sgblack@eecs.umich.edu
5017435Sgblack@eecs.umich.edu    pkt->allocate();
5027435Sgblack@eecs.umich.edu
5037435Sgblack@eecs.umich.edu    //The mask is to give you only the offset into the device register file
5047639Sgblack@eecs.umich.edu    Addr daddr = pkt->getAddr() & 0xfff;
5057639Sgblack@eecs.umich.edu    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x size=%d\n",
5067435Sgblack@eecs.umich.edu            daddr, pkt->getAddr(), pkt->getSize());
5077639Sgblack@eecs.umich.edu
5087639Sgblack@eecs.umich.edu
5097435Sgblack@eecs.umich.edu    // there are some reserved registers, you can see ns_gige_reg.h and
5107435Sgblack@eecs.umich.edu    // the spec sheet for details
5117435Sgblack@eecs.umich.edu    if (daddr > LAST && daddr <=  RESERVED) {
5127639Sgblack@eecs.umich.edu        panic("Accessing reserved register");
5137639Sgblack@eecs.umich.edu    } else if (daddr > RESERVED && daddr <= 0x3FC) {
5147435Sgblack@eecs.umich.edu        return readConfig(pkt);
5157435Sgblack@eecs.umich.edu    } else if (daddr >= MIB_START && daddr <= MIB_END) {
5167639Sgblack@eecs.umich.edu        // don't implement all the MIB's.  hopefully the kernel
5177435Sgblack@eecs.umich.edu        // doesn't actually DEPEND upon their values
5187435Sgblack@eecs.umich.edu        // MIB are just hardware stats keepers
5197639Sgblack@eecs.umich.edu        pkt->set<uint32_t>(0);
5207639Sgblack@eecs.umich.edu        pkt->result = Packet::Success;
5217435Sgblack@eecs.umich.edu        return pioDelay;
5227435Sgblack@eecs.umich.edu    } else if (daddr > 0x3FC)
5237639Sgblack@eecs.umich.edu        panic("Something is messed up!\n");
5247639Sgblack@eecs.umich.edu
5257435Sgblack@eecs.umich.edu    assert(pkt->getSize() == sizeof(uint32_t));
5267435Sgblack@eecs.umich.edu        uint32_t &reg = *pkt->getPtr<uint32_t>();
5277435Sgblack@eecs.umich.edu        uint16_t rfaddr;
5287435Sgblack@eecs.umich.edu
5297435Sgblack@eecs.umich.edu        switch (daddr) {
5307639Sgblack@eecs.umich.edu          case CR:
5317639Sgblack@eecs.umich.edu            reg = regs.command;
5327435Sgblack@eecs.umich.edu            //these are supposed to be cleared on a read
5337639Sgblack@eecs.umich.edu            reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
5347639Sgblack@eecs.umich.edu            break;
5357435Sgblack@eecs.umich.edu
5367435Sgblack@eecs.umich.edu          case CFGR:
5377435Sgblack@eecs.umich.edu            reg = regs.config;
5387639Sgblack@eecs.umich.edu            break;
5397639Sgblack@eecs.umich.edu
5407435Sgblack@eecs.umich.edu          case MEAR:
5417639Sgblack@eecs.umich.edu            reg = regs.mear;
5427639Sgblack@eecs.umich.edu            break;
5437435Sgblack@eecs.umich.edu
5447435Sgblack@eecs.umich.edu          case PTSCR:
5457435Sgblack@eecs.umich.edu            reg = regs.ptscr;
5467435Sgblack@eecs.umich.edu            break;
5477435Sgblack@eecs.umich.edu
5487639Sgblack@eecs.umich.edu          case ISR:
5497639Sgblack@eecs.umich.edu            reg = regs.isr;
5507435Sgblack@eecs.umich.edu            devIntrClear(ISR_ALL);
5517639Sgblack@eecs.umich.edu            break;
5527639Sgblack@eecs.umich.edu
5537435Sgblack@eecs.umich.edu          case IMR:
5547435Sgblack@eecs.umich.edu            reg = regs.imr;
5557435Sgblack@eecs.umich.edu            break;
5567639Sgblack@eecs.umich.edu
5577639Sgblack@eecs.umich.edu          case IER:
5587435Sgblack@eecs.umich.edu            reg = regs.ier;
5597639Sgblack@eecs.umich.edu            break;
5607639Sgblack@eecs.umich.edu
5617435Sgblack@eecs.umich.edu          case IHR:
5627435Sgblack@eecs.umich.edu            reg = regs.ihr;
5637435Sgblack@eecs.umich.edu            break;
5647435Sgblack@eecs.umich.edu
5657639Sgblack@eecs.umich.edu          case TXDP:
5667639Sgblack@eecs.umich.edu            reg = regs.txdp;
5677435Sgblack@eecs.umich.edu            break;
5687639Sgblack@eecs.umich.edu
5697639Sgblack@eecs.umich.edu          case TXDP_HI:
5707435Sgblack@eecs.umich.edu            reg = regs.txdp_hi;
5717435Sgblack@eecs.umich.edu            break;
5727435Sgblack@eecs.umich.edu
5737435Sgblack@eecs.umich.edu          case TX_CFG:
5747435Sgblack@eecs.umich.edu            reg = regs.txcfg;
5757435Sgblack@eecs.umich.edu            break;
5767639Sgblack@eecs.umich.edu
5777639Sgblack@eecs.umich.edu          case GPIOR:
5787435Sgblack@eecs.umich.edu            reg = regs.gpior;
5797435Sgblack@eecs.umich.edu            break;
5807435Sgblack@eecs.umich.edu
5817639Sgblack@eecs.umich.edu          case RXDP:
5827639Sgblack@eecs.umich.edu            reg = regs.rxdp;
5837435Sgblack@eecs.umich.edu            break;
5847639Sgblack@eecs.umich.edu
5857639Sgblack@eecs.umich.edu          case RXDP_HI:
5867435Sgblack@eecs.umich.edu            reg = regs.rxdp_hi;
5877435Sgblack@eecs.umich.edu            break;
5887435Sgblack@eecs.umich.edu
5897435Sgblack@eecs.umich.edu          case RX_CFG:
5907435Sgblack@eecs.umich.edu            reg = regs.rxcfg;
5917435Sgblack@eecs.umich.edu            break;
5927435Sgblack@eecs.umich.edu
5937435Sgblack@eecs.umich.edu          case PQCR:
5947639Sgblack@eecs.umich.edu            reg = regs.pqcr;
5957639Sgblack@eecs.umich.edu            break;
5967639Sgblack@eecs.umich.edu
5977639Sgblack@eecs.umich.edu          case WCSR:
5987639Sgblack@eecs.umich.edu            reg = regs.wcsr;
5997435Sgblack@eecs.umich.edu            break;
6007435Sgblack@eecs.umich.edu
6017435Sgblack@eecs.umich.edu          case PCR:
6027435Sgblack@eecs.umich.edu            reg = regs.pcr;
6037435Sgblack@eecs.umich.edu            break;
6047639Sgblack@eecs.umich.edu
6057639Sgblack@eecs.umich.edu            // see the spec sheet for how RFCR and RFDR work
6067639Sgblack@eecs.umich.edu            // basically, you write to RFCR to tell the machine
6077639Sgblack@eecs.umich.edu            // what you want to do next, then you act upon RFDR,
6087639Sgblack@eecs.umich.edu            // and the device will be prepared b/c of what you
6097435Sgblack@eecs.umich.edu            // wrote to RFCR
6107639Sgblack@eecs.umich.edu          case RFCR:
6117639Sgblack@eecs.umich.edu            reg = regs.rfcr;
6127639Sgblack@eecs.umich.edu            break;
6137639Sgblack@eecs.umich.edu
6147639Sgblack@eecs.umich.edu          case RFDR:
6157435Sgblack@eecs.umich.edu            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
6167435Sgblack@eecs.umich.edu            switch (rfaddr) {
6177435Sgblack@eecs.umich.edu              // Read from perfect match ROM octets
6187435Sgblack@eecs.umich.edu              case 0x000:
6197435Sgblack@eecs.umich.edu                reg = rom.perfectMatch[1];
6207639Sgblack@eecs.umich.edu                reg = reg << 8;
6217639Sgblack@eecs.umich.edu                reg += rom.perfectMatch[0];
6227639Sgblack@eecs.umich.edu                break;
6237639Sgblack@eecs.umich.edu              case 0x002:
6247639Sgblack@eecs.umich.edu                reg = rom.perfectMatch[3] << 8;
6257435Sgblack@eecs.umich.edu                reg += rom.perfectMatch[2];
6267639Sgblack@eecs.umich.edu                break;
6277639Sgblack@eecs.umich.edu              case 0x004:
6287639Sgblack@eecs.umich.edu                reg = rom.perfectMatch[5] << 8;
6297639Sgblack@eecs.umich.edu                reg += rom.perfectMatch[4];
6307639Sgblack@eecs.umich.edu                break;
6317435Sgblack@eecs.umich.edu              default:
6327435Sgblack@eecs.umich.edu                // Read filter hash table
6337435Sgblack@eecs.umich.edu                if (rfaddr >= FHASH_ADDR &&
6347639Sgblack@eecs.umich.edu                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
6357639Sgblack@eecs.umich.edu
6367639Sgblack@eecs.umich.edu                    // Only word-aligned reads supported
6377639Sgblack@eecs.umich.edu                    if (rfaddr % 2)
6387639Sgblack@eecs.umich.edu                        panic("unaligned read from filter hash table!");
6397435Sgblack@eecs.umich.edu
6407639Sgblack@eecs.umich.edu                    reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
6417639Sgblack@eecs.umich.edu                    reg += rom.filterHash[rfaddr - FHASH_ADDR];
6427639Sgblack@eecs.umich.edu                    break;
6437639Sgblack@eecs.umich.edu                }
6447639Sgblack@eecs.umich.edu
6457435Sgblack@eecs.umich.edu                panic("reading RFDR for something other than pattern"
6467435Sgblack@eecs.umich.edu                      " matching or hashing! %#x\n", rfaddr);
6477435Sgblack@eecs.umich.edu            }
6487435Sgblack@eecs.umich.edu            break;
6497435Sgblack@eecs.umich.edu
6507435Sgblack@eecs.umich.edu          case SRR:
6517435Sgblack@eecs.umich.edu            reg = regs.srr;
6527639Sgblack@eecs.umich.edu            break;
6537639Sgblack@eecs.umich.edu
6547639Sgblack@eecs.umich.edu          case MIBC:
6557639Sgblack@eecs.umich.edu            reg = regs.mibc;
6567639Sgblack@eecs.umich.edu            reg &= ~(MIBC_MIBS | MIBC_ACLR);
6577435Sgblack@eecs.umich.edu            break;
6587639Sgblack@eecs.umich.edu
6597639Sgblack@eecs.umich.edu          case VRCR:
6607639Sgblack@eecs.umich.edu            reg = regs.vrcr;
6617639Sgblack@eecs.umich.edu            break;
6627639Sgblack@eecs.umich.edu
6637435Sgblack@eecs.umich.edu          case VTCR:
6647435Sgblack@eecs.umich.edu            reg = regs.vtcr;
6657435Sgblack@eecs.umich.edu            break;
6667435Sgblack@eecs.umich.edu
6677435Sgblack@eecs.umich.edu          case VDR:
6687435Sgblack@eecs.umich.edu            reg = regs.vdr;
6697435Sgblack@eecs.umich.edu            break;
6707639Sgblack@eecs.umich.edu
6717639Sgblack@eecs.umich.edu          case CCSR:
6727639Sgblack@eecs.umich.edu            reg = regs.ccsr;
6737639Sgblack@eecs.umich.edu            break;
6747639Sgblack@eecs.umich.edu
6757435Sgblack@eecs.umich.edu          case TBICR:
6767639Sgblack@eecs.umich.edu            reg = regs.tbicr;
6777639Sgblack@eecs.umich.edu            break;
6787639Sgblack@eecs.umich.edu
6797639Sgblack@eecs.umich.edu          case TBISR:
6807639Sgblack@eecs.umich.edu            reg = regs.tbisr;
6817435Sgblack@eecs.umich.edu            break;
6827435Sgblack@eecs.umich.edu
6837435Sgblack@eecs.umich.edu          case TANAR:
6847639Sgblack@eecs.umich.edu            reg = regs.tanar;
6857639Sgblack@eecs.umich.edu            break;
6867639Sgblack@eecs.umich.edu
6877639Sgblack@eecs.umich.edu          case TANLPAR:
6887639Sgblack@eecs.umich.edu            reg = regs.tanlpar;
6897435Sgblack@eecs.umich.edu            break;
6907435Sgblack@eecs.umich.edu
6917435Sgblack@eecs.umich.edu          case TANER:
6927435Sgblack@eecs.umich.edu            reg = regs.taner;
6937435Sgblack@eecs.umich.edu            break;
6947435Sgblack@eecs.umich.edu
6957435Sgblack@eecs.umich.edu          case TESR:
6967435Sgblack@eecs.umich.edu            reg = regs.tesr;
6977435Sgblack@eecs.umich.edu            break;
6987435Sgblack@eecs.umich.edu
6997435Sgblack@eecs.umich.edu          case M5REG:
7007639Sgblack@eecs.umich.edu            reg = 0;
7017639Sgblack@eecs.umich.edu            if (params()->rx_thread)
7027639Sgblack@eecs.umich.edu                reg |= M5REG_RX_THREAD;
7037639Sgblack@eecs.umich.edu            if (params()->tx_thread)
7047639Sgblack@eecs.umich.edu                reg |= M5REG_TX_THREAD;
7057435Sgblack@eecs.umich.edu            if (params()->rss)
7067639Sgblack@eecs.umich.edu                reg |= M5REG_RSS;
7077639Sgblack@eecs.umich.edu            break;
7087639Sgblack@eecs.umich.edu
7097639Sgblack@eecs.umich.edu          default:
7107639Sgblack@eecs.umich.edu            panic("reading unimplemented register: addr=%#x", daddr);
7117435Sgblack@eecs.umich.edu        }
7127435Sgblack@eecs.umich.edu
7137435Sgblack@eecs.umich.edu        DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
7147435Sgblack@eecs.umich.edu                daddr, reg, reg);
7157435Sgblack@eecs.umich.edu
7167639Sgblack@eecs.umich.edu    pkt->result = Packet::Success;
7177639Sgblack@eecs.umich.edu    return pioDelay;
7187639Sgblack@eecs.umich.edu}
7197639Sgblack@eecs.umich.edu
7207639Sgblack@eecs.umich.eduTick
7217435Sgblack@eecs.umich.eduNSGigE::write(Packet *pkt)
7227639Sgblack@eecs.umich.edu{
7237639Sgblack@eecs.umich.edu    assert(ioEnable);
7247639Sgblack@eecs.umich.edu
7257639Sgblack@eecs.umich.edu    Addr daddr = pkt->getAddr() & 0xfff;
7267639Sgblack@eecs.umich.edu    DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
7277435Sgblack@eecs.umich.edu            daddr, pkt->getAddr(), pkt->getSize());
7287435Sgblack@eecs.umich.edu
7297435Sgblack@eecs.umich.edu    if (daddr > LAST && daddr <=  RESERVED) {
7307639Sgblack@eecs.umich.edu        panic("Accessing reserved register");
7317639Sgblack@eecs.umich.edu    } else if (daddr > RESERVED && daddr <= 0x3FC) {
7327639Sgblack@eecs.umich.edu        return writeConfig(pkt);
7337639Sgblack@eecs.umich.edu    } else if (daddr > 0x3FC)
7347639Sgblack@eecs.umich.edu        panic("Something is messed up!\n");
7357435Sgblack@eecs.umich.edu
7367639Sgblack@eecs.umich.edu    if (pkt->getSize() == sizeof(uint32_t)) {
7377639Sgblack@eecs.umich.edu        uint32_t reg = pkt->get<uint32_t>();
7387639Sgblack@eecs.umich.edu        uint16_t rfaddr;
7397639Sgblack@eecs.umich.edu
7407639Sgblack@eecs.umich.edu        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
7417435Sgblack@eecs.umich.edu
7427435Sgblack@eecs.umich.edu        switch (daddr) {
7437435Sgblack@eecs.umich.edu          case CR:
7447435Sgblack@eecs.umich.edu            regs.command = reg;
7457435Sgblack@eecs.umich.edu            if (reg & CR_TXD) {
7467435Sgblack@eecs.umich.edu                txEnable = false;
7477435Sgblack@eecs.umich.edu            } else if (reg & CR_TXE) {
7487435Sgblack@eecs.umich.edu                txEnable = true;
7497435Sgblack@eecs.umich.edu
7507435Sgblack@eecs.umich.edu                // the kernel is enabling the transmit machine
7517639Sgblack@eecs.umich.edu                if (txState == txIdle)
7527639Sgblack@eecs.umich.edu                    txKick();
7537639Sgblack@eecs.umich.edu            }
7547639Sgblack@eecs.umich.edu
7557435Sgblack@eecs.umich.edu            if (reg & CR_RXD) {
7567639Sgblack@eecs.umich.edu                rxEnable = false;
7577639Sgblack@eecs.umich.edu            } else if (reg & CR_RXE) {
7587639Sgblack@eecs.umich.edu                rxEnable = true;
7597639Sgblack@eecs.umich.edu
7607639Sgblack@eecs.umich.edu                if (rxState == rxIdle)
7617853SMatt.Horsnell@ARM.com                    rxKick();
7627853SMatt.Horsnell@ARM.com            }
7637853SMatt.Horsnell@ARM.com
7647853SMatt.Horsnell@ARM.com            if (reg & CR_TXR)
7657853SMatt.Horsnell@ARM.com                txReset();
7667853SMatt.Horsnell@ARM.com
7677853SMatt.Horsnell@ARM.com            if (reg & CR_RXR)
7687853SMatt.Horsnell@ARM.com                rxReset();
7697853SMatt.Horsnell@ARM.com
7707435Sgblack@eecs.umich.edu            if (reg & CR_SWI)
7717435Sgblack@eecs.umich.edu                devIntrPost(ISR_SWI);
7727435Sgblack@eecs.umich.edu
7737639Sgblack@eecs.umich.edu            if (reg & CR_RST) {
7747639Sgblack@eecs.umich.edu                txReset();
7757639Sgblack@eecs.umich.edu                rxReset();
7767639Sgblack@eecs.umich.edu
7777435Sgblack@eecs.umich.edu                regsReset();
7787639Sgblack@eecs.umich.edu            }
7797639Sgblack@eecs.umich.edu            break;
7807639Sgblack@eecs.umich.edu
7817639Sgblack@eecs.umich.edu          case CFGR:
7827435Sgblack@eecs.umich.edu            if (reg & CFGR_LNKSTS ||
7837435Sgblack@eecs.umich.edu                reg & CFGR_SPDSTS ||
7847435Sgblack@eecs.umich.edu                reg & CFGR_DUPSTS ||
7857639Sgblack@eecs.umich.edu                reg & CFGR_RESERVED ||
7867639Sgblack@eecs.umich.edu                reg & CFGR_T64ADDR ||
7877639Sgblack@eecs.umich.edu                reg & CFGR_PCI64_DET)
7887639Sgblack@eecs.umich.edu
7897639Sgblack@eecs.umich.edu            // First clear all writable bits
7907639Sgblack@eecs.umich.edu            regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
7917639Sgblack@eecs.umich.edu                                   CFGR_RESERVED | CFGR_T64ADDR |
7927639Sgblack@eecs.umich.edu                                   CFGR_PCI64_DET;
7937639Sgblack@eecs.umich.edu            // Now set the appropriate writable bits
7947639Sgblack@eecs.umich.edu            regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
7957639Sgblack@eecs.umich.edu                                   CFGR_RESERVED | CFGR_T64ADDR |
7967639Sgblack@eecs.umich.edu                                   CFGR_PCI64_DET);
7977639Sgblack@eecs.umich.edu
7987639Sgblack@eecs.umich.edu// all these #if 0's are because i don't THINK the kernel needs to
7997639Sgblack@eecs.umich.edu// have these implemented. if there is a problem relating to one of
8007639Sgblack@eecs.umich.edu// these, you may need to add functionality in.
8017639Sgblack@eecs.umich.edu            if (reg & CFGR_TBI_EN) ;
8027639Sgblack@eecs.umich.edu            if (reg & CFGR_MODE_1000) ;
8037435Sgblack@eecs.umich.edu
8047435Sgblack@eecs.umich.edu            if (reg & CFGR_AUTO_1000)
8057639Sgblack@eecs.umich.edu                panic("CFGR_AUTO_1000 not implemented!\n");
8067639Sgblack@eecs.umich.edu
8077639Sgblack@eecs.umich.edu            if (reg & CFGR_PINT_DUPSTS ||
8087639Sgblack@eecs.umich.edu                reg & CFGR_PINT_LNKSTS ||
8097435Sgblack@eecs.umich.edu                reg & CFGR_PINT_SPDSTS)
8107639Sgblack@eecs.umich.edu                ;
8117639Sgblack@eecs.umich.edu
8127639Sgblack@eecs.umich.edu            if (reg & CFGR_TMRTEST) ;
8137639Sgblack@eecs.umich.edu            if (reg & CFGR_MRM_DIS) ;
8147435Sgblack@eecs.umich.edu            if (reg & CFGR_MWI_DIS) ;
8157435Sgblack@eecs.umich.edu
8167435Sgblack@eecs.umich.edu            if (reg & CFGR_T64ADDR) ;
8177435Sgblack@eecs.umich.edu            // panic("CFGR_T64ADDR is read only register!\n");
8187435Sgblack@eecs.umich.edu
8197435Sgblack@eecs.umich.edu            if (reg & CFGR_PCI64_DET)
8207639Sgblack@eecs.umich.edu                panic("CFGR_PCI64_DET is read only register!\n");
8217639Sgblack@eecs.umich.edu
8227639Sgblack@eecs.umich.edu            if (reg & CFGR_DATA64_EN) ;
8237639Sgblack@eecs.umich.edu            if (reg & CFGR_M64ADDR) ;
8247435Sgblack@eecs.umich.edu            if (reg & CFGR_PHY_RST) ;
8257639Sgblack@eecs.umich.edu            if (reg & CFGR_PHY_DIS) ;
8267639Sgblack@eecs.umich.edu
8277639Sgblack@eecs.umich.edu            if (reg & CFGR_EXTSTS_EN)
8287639Sgblack@eecs.umich.edu                extstsEnable = true;
8297435Sgblack@eecs.umich.edu            else
8307435Sgblack@eecs.umich.edu                extstsEnable = false;
8317435Sgblack@eecs.umich.edu
8327639Sgblack@eecs.umich.edu            if (reg & CFGR_REQALG) ;
8337639Sgblack@eecs.umich.edu            if (reg & CFGR_SB) ;
8347639Sgblack@eecs.umich.edu            if (reg & CFGR_POW) ;
8357639Sgblack@eecs.umich.edu            if (reg & CFGR_EXD) ;
8367435Sgblack@eecs.umich.edu            if (reg & CFGR_PESEL) ;
8377435Sgblack@eecs.umich.edu            if (reg & CFGR_BROM_DIS) ;
8387639Sgblack@eecs.umich.edu            if (reg & CFGR_EXT_125) ;
8397639Sgblack@eecs.umich.edu            if (reg & CFGR_BEM) ;
8407639Sgblack@eecs.umich.edu            break;
8417639Sgblack@eecs.umich.edu
8427435Sgblack@eecs.umich.edu          case MEAR:
8437639Sgblack@eecs.umich.edu            // Clear writable bits
8447639Sgblack@eecs.umich.edu            regs.mear &= MEAR_EEDO;
8457639Sgblack@eecs.umich.edu            // Set appropriate writable bits
8467639Sgblack@eecs.umich.edu            regs.mear |= reg & ~MEAR_EEDO;
8477435Sgblack@eecs.umich.edu
8487435Sgblack@eecs.umich.edu            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
8497435Sgblack@eecs.umich.edu            // even though it could get it through RFDR
8507435Sgblack@eecs.umich.edu            if (reg & MEAR_EESEL) {
8517435Sgblack@eecs.umich.edu                // Rising edge of clock
8527435Sgblack@eecs.umich.edu                if (reg & MEAR_EECLK && !eepromClk)
8537435Sgblack@eecs.umich.edu                    eepromKick();
8547435Sgblack@eecs.umich.edu            }
8557435Sgblack@eecs.umich.edu            else {
8567435Sgblack@eecs.umich.edu                eepromState = eepromStart;
8577435Sgblack@eecs.umich.edu                regs.mear &= ~MEAR_EEDI;
8587435Sgblack@eecs.umich.edu            }
8597435Sgblack@eecs.umich.edu
8607435Sgblack@eecs.umich.edu            eepromClk = reg & MEAR_EECLK;
8617639Sgblack@eecs.umich.edu
8627639Sgblack@eecs.umich.edu            // since phy is completely faked, MEAR_MD* don't matter
8637639Sgblack@eecs.umich.edu            if (reg & MEAR_MDIO) ;
8647639Sgblack@eecs.umich.edu            if (reg & MEAR_MDDIR) ;
8657639Sgblack@eecs.umich.edu            if (reg & MEAR_MDC) ;
8667639Sgblack@eecs.umich.edu            break;
8677639Sgblack@eecs.umich.edu
8687639Sgblack@eecs.umich.edu          case PTSCR:
8697639Sgblack@eecs.umich.edu            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
8707639Sgblack@eecs.umich.edu            // these control BISTs for various parts of chip - we
8717639Sgblack@eecs.umich.edu            // don't care or do just fake that the BIST is done
8727639Sgblack@eecs.umich.edu            if (reg & PTSCR_RBIST_EN)
8737639Sgblack@eecs.umich.edu                regs.ptscr |= PTSCR_RBIST_DONE;
8747639Sgblack@eecs.umich.edu            if (reg & PTSCR_EEBIST_EN)
8757639Sgblack@eecs.umich.edu                regs.ptscr &= ~PTSCR_EEBIST_EN;
8767639Sgblack@eecs.umich.edu            if (reg & PTSCR_EELOAD_EN)
8777639Sgblack@eecs.umich.edu                regs.ptscr &= ~PTSCR_EELOAD_EN;
8787639Sgblack@eecs.umich.edu            break;
8797639Sgblack@eecs.umich.edu
8807639Sgblack@eecs.umich.edu          case ISR: /* writing to the ISR has no effect */
8817639Sgblack@eecs.umich.edu            panic("ISR is a read only register!\n");
8827639Sgblack@eecs.umich.edu
8837639Sgblack@eecs.umich.edu          case IMR:
8847639Sgblack@eecs.umich.edu            regs.imr = reg;
8857639Sgblack@eecs.umich.edu            devIntrChangeMask();
8867639Sgblack@eecs.umich.edu            break;
8877435Sgblack@eecs.umich.edu
8887435Sgblack@eecs.umich.edu          case IER:
8897435Sgblack@eecs.umich.edu            regs.ier = reg;
8907639Sgblack@eecs.umich.edu            break;
8917639Sgblack@eecs.umich.edu
8927435Sgblack@eecs.umich.edu          case IHR:
8937639Sgblack@eecs.umich.edu            regs.ihr = reg;
8947639Sgblack@eecs.umich.edu            /* not going to implement real interrupt holdoff */
8957435Sgblack@eecs.umich.edu            break;
8967639Sgblack@eecs.umich.edu
8977639Sgblack@eecs.umich.edu          case TXDP:
8987435Sgblack@eecs.umich.edu            regs.txdp = (reg & 0xFFFFFFFC);
8997639Sgblack@eecs.umich.edu            assert(txState == txIdle);
9007639Sgblack@eecs.umich.edu            CTDD = false;
9017435Sgblack@eecs.umich.edu            break;
9027435Sgblack@eecs.umich.edu
9037639Sgblack@eecs.umich.edu          case TXDP_HI:
9047639Sgblack@eecs.umich.edu            regs.txdp_hi = reg;
9057435Sgblack@eecs.umich.edu            break;
9067435Sgblack@eecs.umich.edu
9077435Sgblack@eecs.umich.edu          case TX_CFG:
9087435Sgblack@eecs.umich.edu            regs.txcfg = reg;
9097435Sgblack@eecs.umich.edu#if 0
9107639Sgblack@eecs.umich.edu            if (reg & TX_CFG_CSI) ;
9117639Sgblack@eecs.umich.edu            if (reg & TX_CFG_HBI) ;
9127435Sgblack@eecs.umich.edu            if (reg & TX_CFG_MLB) ;
9137639Sgblack@eecs.umich.edu            if (reg & TX_CFG_ATP) ;
9147639Sgblack@eecs.umich.edu            if (reg & TX_CFG_ECRETRY) {
9157435Sgblack@eecs.umich.edu                /*
9167435Sgblack@eecs.umich.edu                 * this could easily be implemented, but considering
9177435Sgblack@eecs.umich.edu                 * the network is just a fake pipe, wouldn't make
9187639Sgblack@eecs.umich.edu                 * sense to do this
9197639Sgblack@eecs.umich.edu                 */
9207639Sgblack@eecs.umich.edu            }
9217639Sgblack@eecs.umich.edu
9227639Sgblack@eecs.umich.edu            if (reg & TX_CFG_BRST_DIS) ;
9237639Sgblack@eecs.umich.edu#endif
9247639Sgblack@eecs.umich.edu
9257639Sgblack@eecs.umich.edu#if 0
9267639Sgblack@eecs.umich.edu            /* we handle our own DMA, ignore the kernel's exhortations */
9277639Sgblack@eecs.umich.edu            if (reg & TX_CFG_MXDMA) ;
9287639Sgblack@eecs.umich.edu#endif
9297639Sgblack@eecs.umich.edu
9307435Sgblack@eecs.umich.edu            // also, we currently don't care about fill/drain
9317435Sgblack@eecs.umich.edu            // thresholds though this may change in the future with
9327435Sgblack@eecs.umich.edu            // more realistic networks or a driver which changes it
9337435Sgblack@eecs.umich.edu            // according to feedback
9347639Sgblack@eecs.umich.edu
9357639Sgblack@eecs.umich.edu            break;
9367435Sgblack@eecs.umich.edu
9377639Sgblack@eecs.umich.edu          case GPIOR:
9387639Sgblack@eecs.umich.edu            // Only write writable bits
9397435Sgblack@eecs.umich.edu            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
9407435Sgblack@eecs.umich.edu                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
9417435Sgblack@eecs.umich.edu            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
9427435Sgblack@eecs.umich.edu                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
9437639Sgblack@eecs.umich.edu            /* these just control general purpose i/o pins, don't matter */
9447639Sgblack@eecs.umich.edu            break;
9457639Sgblack@eecs.umich.edu
9467435Sgblack@eecs.umich.edu          case RXDP:
9477639Sgblack@eecs.umich.edu            regs.rxdp = reg;
9487639Sgblack@eecs.umich.edu            CRDD = false;
9497435Sgblack@eecs.umich.edu            break;
9507435Sgblack@eecs.umich.edu
9517435Sgblack@eecs.umich.edu          case RXDP_HI:
9527435Sgblack@eecs.umich.edu            regs.rxdp_hi = reg;
9537435Sgblack@eecs.umich.edu            break;
9547639Sgblack@eecs.umich.edu
9557639Sgblack@eecs.umich.edu          case RX_CFG:
9567435Sgblack@eecs.umich.edu            regs.rxcfg = reg;
9577435Sgblack@eecs.umich.edu#if 0
9587639Sgblack@eecs.umich.edu            if (reg & RX_CFG_AEP) ;
9597639Sgblack@eecs.umich.edu            if (reg & RX_CFG_ARP) ;
9607639Sgblack@eecs.umich.edu            if (reg & RX_CFG_STRIPCRC) ;
9617639Sgblack@eecs.umich.edu            if (reg & RX_CFG_RX_RD) ;
9627639Sgblack@eecs.umich.edu            if (reg & RX_CFG_ALP) ;
9637639Sgblack@eecs.umich.edu            if (reg & RX_CFG_AIRL) ;
9647639Sgblack@eecs.umich.edu
9657639Sgblack@eecs.umich.edu            /* we handle our own DMA, ignore what kernel says about it */
9667639Sgblack@eecs.umich.edu            if (reg & RX_CFG_MXDMA) ;
9677639Sgblack@eecs.umich.edu
9687639Sgblack@eecs.umich.edu            //also, we currently don't care about fill/drain thresholds
9697639Sgblack@eecs.umich.edu            //though this may change in the future with more realistic
9707639Sgblack@eecs.umich.edu            //networks or a driver which changes it according to feedback
9717639Sgblack@eecs.umich.edu            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
9727639Sgblack@eecs.umich.edu#endif
9737639Sgblack@eecs.umich.edu            break;
9747639Sgblack@eecs.umich.edu
9757639Sgblack@eecs.umich.edu          case PQCR:
9767639Sgblack@eecs.umich.edu            /* there is no priority queueing used in the linux 2.6 driver */
9777639Sgblack@eecs.umich.edu            regs.pqcr = reg;
9787639Sgblack@eecs.umich.edu            break;
9797639Sgblack@eecs.umich.edu
9807639Sgblack@eecs.umich.edu          case WCSR:
9817435Sgblack@eecs.umich.edu            /* not going to implement wake on LAN */
9827435Sgblack@eecs.umich.edu            regs.wcsr = reg;
9837435Sgblack@eecs.umich.edu            break;
9847639Sgblack@eecs.umich.edu
9857639Sgblack@eecs.umich.edu          case PCR:
9867639Sgblack@eecs.umich.edu            /* not going to implement pause control */
9877639Sgblack@eecs.umich.edu            regs.pcr = reg;
9887639Sgblack@eecs.umich.edu            break;
9897639Sgblack@eecs.umich.edu
9907639Sgblack@eecs.umich.edu          case RFCR:
9917639Sgblack@eecs.umich.edu            regs.rfcr = reg;
9927639Sgblack@eecs.umich.edu
9937639Sgblack@eecs.umich.edu            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
9947639Sgblack@eecs.umich.edu            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
9957639Sgblack@eecs.umich.edu            acceptMulticast = (reg & RFCR_AAM) ? true : false;
9967639Sgblack@eecs.umich.edu            acceptUnicast = (reg & RFCR_AAU) ? true : false;
9977639Sgblack@eecs.umich.edu            acceptPerfect = (reg & RFCR_APM) ? true : false;
9987639Sgblack@eecs.umich.edu            acceptArp = (reg & RFCR_AARP) ? true : false;
9997639Sgblack@eecs.umich.edu            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
10007639Sgblack@eecs.umich.edu
10017639Sgblack@eecs.umich.edu#if 0
10027639Sgblack@eecs.umich.edu            if (reg & RFCR_APAT)
10037639Sgblack@eecs.umich.edu                panic("RFCR_APAT not implemented!\n");
10047435Sgblack@eecs.umich.edu#endif
10057435Sgblack@eecs.umich.edu            if (reg & RFCR_UHEN)
10067435Sgblack@eecs.umich.edu                panic("Unicast hash filtering not used by drivers!\n");
10077435Sgblack@eecs.umich.edu
10087435Sgblack@eecs.umich.edu            if (reg & RFCR_ULM)
10097435Sgblack@eecs.umich.edu                panic("RFCR_ULM not implemented!\n");
10107435Sgblack@eecs.umich.edu
10117435Sgblack@eecs.umich.edu            break;
10127435Sgblack@eecs.umich.edu
10137435Sgblack@eecs.umich.edu          case RFDR:
10147639Sgblack@eecs.umich.edu            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
10157639Sgblack@eecs.umich.edu            switch (rfaddr) {
10167639Sgblack@eecs.umich.edu              case 0x000:
10177639Sgblack@eecs.umich.edu                rom.perfectMatch[0] = (uint8_t)reg;
10187639Sgblack@eecs.umich.edu                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
10197639Sgblack@eecs.umich.edu                break;
10207639Sgblack@eecs.umich.edu              case 0x002:
10217639Sgblack@eecs.umich.edu                rom.perfectMatch[2] = (uint8_t)reg;
10227639Sgblack@eecs.umich.edu                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
10237639Sgblack@eecs.umich.edu                break;
10247435Sgblack@eecs.umich.edu              case 0x004:
10257435Sgblack@eecs.umich.edu                rom.perfectMatch[4] = (uint8_t)reg;
10267639Sgblack@eecs.umich.edu                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
10277639Sgblack@eecs.umich.edu                break;
10287435Sgblack@eecs.umich.edu              default:
10297639Sgblack@eecs.umich.edu
10307639Sgblack@eecs.umich.edu                if (rfaddr >= FHASH_ADDR &&
10317435Sgblack@eecs.umich.edu                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
10327639Sgblack@eecs.umich.edu
10337639Sgblack@eecs.umich.edu                    // Only word-aligned writes supported
10347435Sgblack@eecs.umich.edu                    if (rfaddr % 2)
10357639Sgblack@eecs.umich.edu                        panic("unaligned write to filter hash table!");
10367639Sgblack@eecs.umich.edu
10377435Sgblack@eecs.umich.edu                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
10387435Sgblack@eecs.umich.edu                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
10397639Sgblack@eecs.umich.edu                        = (uint8_t)(reg >> 8);
10407639Sgblack@eecs.umich.edu                    break;
10417435Sgblack@eecs.umich.edu                }
10427639Sgblack@eecs.umich.edu                panic("writing RFDR for something other than pattern matching\
10437639Sgblack@eecs.umich.edu                    or hashing! %#x\n", rfaddr);
10447435Sgblack@eecs.umich.edu            }
10457435Sgblack@eecs.umich.edu
10467639Sgblack@eecs.umich.edu          case BRAR:
10477639Sgblack@eecs.umich.edu            regs.brar = reg;
10487435Sgblack@eecs.umich.edu            break;
10497435Sgblack@eecs.umich.edu
10507639Sgblack@eecs.umich.edu          case BRDR:
10517639Sgblack@eecs.umich.edu            panic("the driver never uses BRDR, something is wrong!\n");
10527435Sgblack@eecs.umich.edu
10537639Sgblack@eecs.umich.edu          case SRR:
10547639Sgblack@eecs.umich.edu            panic("SRR is read only register!\n");
10557435Sgblack@eecs.umich.edu
10567435Sgblack@eecs.umich.edu          case MIBC:
10577435Sgblack@eecs.umich.edu            panic("the driver never uses MIBC, something is wrong!\n");
10587639Sgblack@eecs.umich.edu
10597639Sgblack@eecs.umich.edu          case VRCR:
10607435Sgblack@eecs.umich.edu            regs.vrcr = reg;
10617639Sgblack@eecs.umich.edu            break;
10627639Sgblack@eecs.umich.edu
10637435Sgblack@eecs.umich.edu          case VTCR:
10647435Sgblack@eecs.umich.edu            regs.vtcr = reg;
10657639Sgblack@eecs.umich.edu            break;
10667639Sgblack@eecs.umich.edu
10677435Sgblack@eecs.umich.edu          case VDR:
10687639Sgblack@eecs.umich.edu            panic("the driver never uses VDR, something is wrong!\n");
10697639Sgblack@eecs.umich.edu
10707435Sgblack@eecs.umich.edu          case CCSR:
10717639Sgblack@eecs.umich.edu            /* not going to implement clockrun stuff */
10727639Sgblack@eecs.umich.edu            regs.ccsr = reg;
10737435Sgblack@eecs.umich.edu            break;
10747639Sgblack@eecs.umich.edu
10757639Sgblack@eecs.umich.edu          case TBICR:
10767435Sgblack@eecs.umich.edu            regs.tbicr = reg;
10777435Sgblack@eecs.umich.edu            if (reg & TBICR_MR_LOOPBACK)
10787639Sgblack@eecs.umich.edu                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
10797435Sgblack@eecs.umich.edu
10807435Sgblack@eecs.umich.edu            if (reg & TBICR_MR_AN_ENABLE) {
10817639Sgblack@eecs.umich.edu                regs.tanlpar = regs.tanar;
10827639Sgblack@eecs.umich.edu                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
10837435Sgblack@eecs.umich.edu            }
10847435Sgblack@eecs.umich.edu
10857639Sgblack@eecs.umich.edu#if 0
10867639Sgblack@eecs.umich.edu            if (reg & TBICR_MR_RESTART_AN) ;
10877435Sgblack@eecs.umich.edu#endif
10887639Sgblack@eecs.umich.edu
10897435Sgblack@eecs.umich.edu            break;
10907435Sgblack@eecs.umich.edu
10917639Sgblack@eecs.umich.edu          case TBISR:
10927639Sgblack@eecs.umich.edu            panic("TBISR is read only register!\n");
10937435Sgblack@eecs.umich.edu
10947435Sgblack@eecs.umich.edu          case TANAR:
10957639Sgblack@eecs.umich.edu            // Only write the writable bits
10967639Sgblack@eecs.umich.edu            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
10977435Sgblack@eecs.umich.edu            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
10987435Sgblack@eecs.umich.edu
10997435Sgblack@eecs.umich.edu            // Pause capability unimplemented
11007435Sgblack@eecs.umich.edu#if 0
11017435Sgblack@eecs.umich.edu            if (reg & TANAR_PS2) ;
11027435Sgblack@eecs.umich.edu            if (reg & TANAR_PS1) ;
11037435Sgblack@eecs.umich.edu#endif
11047435Sgblack@eecs.umich.edu
11057435Sgblack@eecs.umich.edu            break;
11067639Sgblack@eecs.umich.edu
11077639Sgblack@eecs.umich.edu          case TANLPAR:
11087639Sgblack@eecs.umich.edu            panic("this should only be written to by the fake phy!\n");
11097639Sgblack@eecs.umich.edu
11107639Sgblack@eecs.umich.edu          case TANER:
11117639Sgblack@eecs.umich.edu            panic("TANER is read only register!\n");
11127639Sgblack@eecs.umich.edu
11137639Sgblack@eecs.umich.edu          case TESR:
11147639Sgblack@eecs.umich.edu            regs.tesr = reg;
11157639Sgblack@eecs.umich.edu            break;
11167639Sgblack@eecs.umich.edu
11177639Sgblack@eecs.umich.edu          default:
11187435Sgblack@eecs.umich.edu            panic("invalid register access daddr=%#x", daddr);
11197435Sgblack@eecs.umich.edu        }
11207639Sgblack@eecs.umich.edu    } else {
11217639Sgblack@eecs.umich.edu        panic("Invalid Request Size");
11227639Sgblack@eecs.umich.edu    }
11237639Sgblack@eecs.umich.edu    pkt->result = Packet::Success;
11247639Sgblack@eecs.umich.edu    return pioDelay;
11257639Sgblack@eecs.umich.edu}
11267639Sgblack@eecs.umich.edu
11277639Sgblack@eecs.umich.eduvoid
11287639Sgblack@eecs.umich.eduNSGigE::devIntrPost(uint32_t interrupts)
11297639Sgblack@eecs.umich.edu{
11307639Sgblack@eecs.umich.edu    if (interrupts & ISR_RESERVE)
11317639Sgblack@eecs.umich.edu        panic("Cannot set a reserved interrupt");
11327639Sgblack@eecs.umich.edu
11337639Sgblack@eecs.umich.edu    if (interrupts & ISR_NOIMPL)
11347639Sgblack@eecs.umich.edu        warn("interrupt not implemented %#x\n", interrupts);
11357639Sgblack@eecs.umich.edu
11367639Sgblack@eecs.umich.edu    interrupts &= ISR_IMPL;
11377639Sgblack@eecs.umich.edu    regs.isr |= interrupts;
11387639Sgblack@eecs.umich.edu
11397435Sgblack@eecs.umich.edu    if (interrupts & regs.imr) {
11407639Sgblack@eecs.umich.edu        if (interrupts & ISR_SWI) {
11417639Sgblack@eecs.umich.edu            totalSwi++;
11427639Sgblack@eecs.umich.edu        }
11437639Sgblack@eecs.umich.edu        if (interrupts & ISR_RXIDLE) {
11447435Sgblack@eecs.umich.edu            totalRxIdle++;
11457639Sgblack@eecs.umich.edu        }
11467639Sgblack@eecs.umich.edu        if (interrupts & ISR_RXOK) {
11477639Sgblack@eecs.umich.edu            totalRxOk++;
11487639Sgblack@eecs.umich.edu        }
11497639Sgblack@eecs.umich.edu        if (interrupts & ISR_RXDESC) {
11507639Sgblack@eecs.umich.edu            totalRxDesc++;
11517639Sgblack@eecs.umich.edu        }
11527639Sgblack@eecs.umich.edu        if (interrupts & ISR_TXOK) {
11537639Sgblack@eecs.umich.edu            totalTxOk++;
11547639Sgblack@eecs.umich.edu        }
11557639Sgblack@eecs.umich.edu        if (interrupts & ISR_TXIDLE) {
11567639Sgblack@eecs.umich.edu            totalTxIdle++;
11577639Sgblack@eecs.umich.edu        }
11587639Sgblack@eecs.umich.edu        if (interrupts & ISR_TXDESC) {
11597639Sgblack@eecs.umich.edu            totalTxDesc++;
11607639Sgblack@eecs.umich.edu        }
11617639Sgblack@eecs.umich.edu        if (interrupts & ISR_RXORN) {
11627639Sgblack@eecs.umich.edu            totalRxOrn++;
11637639Sgblack@eecs.umich.edu        }
11647435Sgblack@eecs.umich.edu    }
11657639Sgblack@eecs.umich.edu
11667639Sgblack@eecs.umich.edu    DPRINTF(EthernetIntr,
11677639Sgblack@eecs.umich.edu            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
11687639Sgblack@eecs.umich.edu            interrupts, regs.isr, regs.imr);
11697435Sgblack@eecs.umich.edu
11707639Sgblack@eecs.umich.edu    if ((regs.isr & regs.imr)) {
11717639Sgblack@eecs.umich.edu        Tick when = curTick;
11727639Sgblack@eecs.umich.edu        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
11737639Sgblack@eecs.umich.edu            when += intrDelay;
11747639Sgblack@eecs.umich.edu        cpuIntrPost(when);
11757639Sgblack@eecs.umich.edu    }
11767639Sgblack@eecs.umich.edu}
11777639Sgblack@eecs.umich.edu
11787639Sgblack@eecs.umich.edu/* writing this interrupt counting stats inside this means that this function
11797639Sgblack@eecs.umich.edu   is now limited to being used to clear all interrupts upon the kernel
11807639Sgblack@eecs.umich.edu   reading isr and servicing.  just telling you in case you were thinking
11817639Sgblack@eecs.umich.edu   of expanding use.
11827639Sgblack@eecs.umich.edu*/
11837639Sgblack@eecs.umich.eduvoid
11847639Sgblack@eecs.umich.eduNSGigE::devIntrClear(uint32_t interrupts)
11857639Sgblack@eecs.umich.edu{
11867639Sgblack@eecs.umich.edu    if (interrupts & ISR_RESERVE)
11877639Sgblack@eecs.umich.edu        panic("Cannot clear a reserved interrupt");
11887639Sgblack@eecs.umich.edu
11897435Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_SWI) {
11907639Sgblack@eecs.umich.edu        postedSwi++;
11917639Sgblack@eecs.umich.edu    }
11927639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_RXIDLE) {
11937639Sgblack@eecs.umich.edu        postedRxIdle++;
11947639Sgblack@eecs.umich.edu    }
11957639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_RXOK) {
11967639Sgblack@eecs.umich.edu        postedRxOk++;
11977639Sgblack@eecs.umich.edu    }
11987639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_RXDESC) {
11997639Sgblack@eecs.umich.edu            postedRxDesc++;
12007639Sgblack@eecs.umich.edu    }
12017639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_TXOK) {
12027639Sgblack@eecs.umich.edu        postedTxOk++;
12037639Sgblack@eecs.umich.edu    }
12047639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_TXIDLE) {
12057639Sgblack@eecs.umich.edu        postedTxIdle++;
12067639Sgblack@eecs.umich.edu    }
12077639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_TXDESC) {
12087639Sgblack@eecs.umich.edu        postedTxDesc++;
12097435Sgblack@eecs.umich.edu    }
12107435Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_RXORN) {
12117435Sgblack@eecs.umich.edu        postedRxOrn++;
12127435Sgblack@eecs.umich.edu    }
12137639Sgblack@eecs.umich.edu
12147639Sgblack@eecs.umich.edu    if (regs.isr & regs.imr & ISR_IMPL)
12157639Sgblack@eecs.umich.edu        postedInterrupts++;
12167639Sgblack@eecs.umich.edu
12177639Sgblack@eecs.umich.edu    interrupts &= ~ISR_NOIMPL;
12187639Sgblack@eecs.umich.edu    regs.isr &= ~interrupts;
12197639Sgblack@eecs.umich.edu
12207639Sgblack@eecs.umich.edu    DPRINTF(EthernetIntr,
12217435Sgblack@eecs.umich.edu            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
12227435Sgblack@eecs.umich.edu            interrupts, regs.isr, regs.imr);
12237435Sgblack@eecs.umich.edu
12247435Sgblack@eecs.umich.edu    if (!(regs.isr & regs.imr))
12257435Sgblack@eecs.umich.edu        cpuIntrClear();
12267639Sgblack@eecs.umich.edu}
12277639Sgblack@eecs.umich.edu
12287639Sgblack@eecs.umich.eduvoid
12297639Sgblack@eecs.umich.eduNSGigE::devIntrChangeMask()
12307639Sgblack@eecs.umich.edu{
12317639Sgblack@eecs.umich.edu    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
12327639Sgblack@eecs.umich.edu            regs.isr, regs.imr, regs.isr & regs.imr);
12337639Sgblack@eecs.umich.edu
12347435Sgblack@eecs.umich.edu    if (regs.isr & regs.imr)
12357435Sgblack@eecs.umich.edu        cpuIntrPost(curTick);
12367639Sgblack@eecs.umich.edu    else
12377639Sgblack@eecs.umich.edu        cpuIntrClear();
12387639Sgblack@eecs.umich.edu}
12397639Sgblack@eecs.umich.edu
12407639Sgblack@eecs.umich.eduvoid
12417639Sgblack@eecs.umich.eduNSGigE::cpuIntrPost(Tick when)
12427639Sgblack@eecs.umich.edu{
12437639Sgblack@eecs.umich.edu    // If the interrupt you want to post is later than an interrupt
12447639Sgblack@eecs.umich.edu    // already scheduled, just let it post in the coming one and don't
12457639Sgblack@eecs.umich.edu    // schedule another.
12467639Sgblack@eecs.umich.edu    // HOWEVER, must be sure that the scheduled intrTick is in the
12477639Sgblack@eecs.umich.edu    // future (this was formerly the source of a bug)
12487639Sgblack@eecs.umich.edu    /**
12497639Sgblack@eecs.umich.edu     * @todo this warning should be removed and the intrTick code should
12507639Sgblack@eecs.umich.edu     * be fixed.
12517639Sgblack@eecs.umich.edu     */
12527639Sgblack@eecs.umich.edu    assert(when >= curTick);
12537639Sgblack@eecs.umich.edu    assert(intrTick >= curTick || intrTick == 0);
12547639Sgblack@eecs.umich.edu    if (when > intrTick && intrTick != 0) {
12557435Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
12567639Sgblack@eecs.umich.edu                intrTick);
12577639Sgblack@eecs.umich.edu        return;
12587639Sgblack@eecs.umich.edu    }
12597639Sgblack@eecs.umich.edu
12607435Sgblack@eecs.umich.edu    intrTick = when;
12617639Sgblack@eecs.umich.edu    if (intrTick < curTick) {
12627639Sgblack@eecs.umich.edu        debug_break();
12637639Sgblack@eecs.umich.edu        intrTick = curTick;
12647639Sgblack@eecs.umich.edu    }
12657639Sgblack@eecs.umich.edu
12667639Sgblack@eecs.umich.edu    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
12677639Sgblack@eecs.umich.edu            intrTick);
12687639Sgblack@eecs.umich.edu
12697639Sgblack@eecs.umich.edu    if (intrEvent)
12707639Sgblack@eecs.umich.edu        intrEvent->squash();
12717639Sgblack@eecs.umich.edu    intrEvent = new IntrEvent(this, true);
12727639Sgblack@eecs.umich.edu    intrEvent->schedule(intrTick);
12737639Sgblack@eecs.umich.edu}
12747639Sgblack@eecs.umich.edu
12757639Sgblack@eecs.umich.eduvoid
12767639Sgblack@eecs.umich.eduNSGigE::cpuInterrupt()
12777639Sgblack@eecs.umich.edu{
12787639Sgblack@eecs.umich.edu    assert(intrTick == curTick);
12797639Sgblack@eecs.umich.edu
12807435Sgblack@eecs.umich.edu    // Whether or not there's a pending interrupt, we don't care about
12817435Sgblack@eecs.umich.edu    // it anymore
12827435Sgblack@eecs.umich.edu    intrEvent = 0;
12837435Sgblack@eecs.umich.edu    intrTick = 0;
12847639Sgblack@eecs.umich.edu
12857639Sgblack@eecs.umich.edu    // Don't send an interrupt if there's already one
12867639Sgblack@eecs.umich.edu    if (cpuPendingIntr) {
12877639Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr,
12887639Sgblack@eecs.umich.edu                "would send an interrupt now, but there's already pending\n");
12897639Sgblack@eecs.umich.edu    } else {
12907639Sgblack@eecs.umich.edu        // Send interrupt
12917639Sgblack@eecs.umich.edu        cpuPendingIntr = true;
12927639Sgblack@eecs.umich.edu
12937639Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr, "posting interrupt\n");
12947639Sgblack@eecs.umich.edu        intrPost();
12957639Sgblack@eecs.umich.edu    }
12967639Sgblack@eecs.umich.edu}
12977639Sgblack@eecs.umich.edu
12987639Sgblack@eecs.umich.eduvoid
12997639Sgblack@eecs.umich.eduNSGigE::cpuIntrClear()
13007639Sgblack@eecs.umich.edu{
13017639Sgblack@eecs.umich.edu    if (!cpuPendingIntr)
13027639Sgblack@eecs.umich.edu        return;
13037639Sgblack@eecs.umich.edu
13047639Sgblack@eecs.umich.edu    if (intrEvent) {
13057639Sgblack@eecs.umich.edu        intrEvent->squash();
13067639Sgblack@eecs.umich.edu        intrEvent = 0;
13077435Sgblack@eecs.umich.edu    }
13087435Sgblack@eecs.umich.edu
13097639Sgblack@eecs.umich.edu    intrTick = 0;
13107639Sgblack@eecs.umich.edu
13117639Sgblack@eecs.umich.edu    cpuPendingIntr = false;
13127639Sgblack@eecs.umich.edu
13137639Sgblack@eecs.umich.edu    DPRINTF(EthernetIntr, "clearing interrupt\n");
13147639Sgblack@eecs.umich.edu    intrClear();
13157639Sgblack@eecs.umich.edu}
13167639Sgblack@eecs.umich.edu
13177639Sgblack@eecs.umich.edubool
13187639Sgblack@eecs.umich.eduNSGigE::cpuIntrPending() const
13197639Sgblack@eecs.umich.edu{ return cpuPendingIntr; }
13207639Sgblack@eecs.umich.edu
13217639Sgblack@eecs.umich.eduvoid
13227639Sgblack@eecs.umich.eduNSGigE::txReset()
13237639Sgblack@eecs.umich.edu{
13247639Sgblack@eecs.umich.edu
13257639Sgblack@eecs.umich.edu    DPRINTF(Ethernet, "transmit reset\n");
13267639Sgblack@eecs.umich.edu
13277639Sgblack@eecs.umich.edu    CTDD = false;
13287639Sgblack@eecs.umich.edu    txEnable = false;;
13297639Sgblack@eecs.umich.edu    txFragPtr = 0;
13307639Sgblack@eecs.umich.edu    assert(txDescCnt == 0);
13317639Sgblack@eecs.umich.edu    txFifo.clear();
13327435Sgblack@eecs.umich.edu    txState = txIdle;
13337639Sgblack@eecs.umich.edu    assert(txDmaState == dmaIdle);
13347639Sgblack@eecs.umich.edu}
13357639Sgblack@eecs.umich.edu
13367639Sgblack@eecs.umich.eduvoid
13377639Sgblack@eecs.umich.eduNSGigE::rxReset()
13387639Sgblack@eecs.umich.edu{
13397639Sgblack@eecs.umich.edu    DPRINTF(Ethernet, "receive reset\n");
13407639Sgblack@eecs.umich.edu
13417639Sgblack@eecs.umich.edu    CRDD = false;
13427639Sgblack@eecs.umich.edu    assert(rxPktBytes == 0);
13437639Sgblack@eecs.umich.edu    rxEnable = false;
13447639Sgblack@eecs.umich.edu    rxFragPtr = 0;
13457639Sgblack@eecs.umich.edu    assert(rxDescCnt == 0);
13467639Sgblack@eecs.umich.edu    assert(rxDmaState == dmaIdle);
13477639Sgblack@eecs.umich.edu    rxFifo.clear();
13487639Sgblack@eecs.umich.edu    rxState = rxIdle;
13497639Sgblack@eecs.umich.edu}
13507639Sgblack@eecs.umich.edu
13517639Sgblack@eecs.umich.eduvoid
13527639Sgblack@eecs.umich.eduNSGigE::regsReset()
13537639Sgblack@eecs.umich.edu{
13547639Sgblack@eecs.umich.edu    memset(&regs, 0, sizeof(regs));
13557639Sgblack@eecs.umich.edu    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
13567435Sgblack@eecs.umich.edu    regs.mear = 0x12;
13577435Sgblack@eecs.umich.edu    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
13587435Sgblack@eecs.umich.edu                        // fill threshold to 32 bytes
13597435Sgblack@eecs.umich.edu    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
13607435Sgblack@eecs.umich.edu    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
13617435Sgblack@eecs.umich.edu    regs.mibc = MIBC_FRZ;
13627435Sgblack@eecs.umich.edu    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
13637435Sgblack@eecs.umich.edu    regs.tesr = 0xc000; // TBI capable of both full and half duplex
13647435Sgblack@eecs.umich.edu    regs.brar = 0xffffffff;
13657639Sgblack@eecs.umich.edu
13667639Sgblack@eecs.umich.edu    extstsEnable = false;
13677639Sgblack@eecs.umich.edu    acceptBroadcast = false;
13687639Sgblack@eecs.umich.edu    acceptMulticast = false;
13697639Sgblack@eecs.umich.edu    acceptUnicast = false;
13707639Sgblack@eecs.umich.edu    acceptPerfect = false;
13717639Sgblack@eecs.umich.edu    acceptArp = false;
13727639Sgblack@eecs.umich.edu}
13737435Sgblack@eecs.umich.edu
13747435Sgblack@eecs.umich.edubool
13757435Sgblack@eecs.umich.eduNSGigE::doRxDmaRead()
13767435Sgblack@eecs.umich.edu{
13777639Sgblack@eecs.umich.edu    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
13787639Sgblack@eecs.umich.edu    rxDmaState = dmaReading;
13797639Sgblack@eecs.umich.edu
13807639Sgblack@eecs.umich.edu    if (dmaPending())
13817639Sgblack@eecs.umich.edu        rxDmaState = dmaReadWaiting;
13827639Sgblack@eecs.umich.edu    else
13837639Sgblack@eecs.umich.edu        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
13847639Sgblack@eecs.umich.edu
13857639Sgblack@eecs.umich.edu    return true;
13867639Sgblack@eecs.umich.edu}
13877639Sgblack@eecs.umich.edu
13887639Sgblack@eecs.umich.eduvoid
13897639Sgblack@eecs.umich.eduNSGigE::rxDmaReadDone()
13907639Sgblack@eecs.umich.edu{
13917639Sgblack@eecs.umich.edu    assert(rxDmaState == dmaReading);
13927639Sgblack@eecs.umich.edu    rxDmaState = dmaIdle;
13937639Sgblack@eecs.umich.edu
13947639Sgblack@eecs.umich.edu    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
13957639Sgblack@eecs.umich.edu            rxDmaAddr, rxDmaLen);
13967639Sgblack@eecs.umich.edu    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
13977639Sgblack@eecs.umich.edu
13987639Sgblack@eecs.umich.edu    // If the transmit state machine has a pending DMA, let it go first
13997435Sgblack@eecs.umich.edu    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
14007639Sgblack@eecs.umich.edu        txKick();
14017639Sgblack@eecs.umich.edu
14027639Sgblack@eecs.umich.edu    rxKick();
14037639Sgblack@eecs.umich.edu}
14047639Sgblack@eecs.umich.edu
14057639Sgblack@eecs.umich.edubool
14067639Sgblack@eecs.umich.eduNSGigE::doRxDmaWrite()
14077639Sgblack@eecs.umich.edu{
14087639Sgblack@eecs.umich.edu    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
14097639Sgblack@eecs.umich.edu    rxDmaState = dmaWriting;
14107639Sgblack@eecs.umich.edu
14117639Sgblack@eecs.umich.edu    if (dmaPending())
14127639Sgblack@eecs.umich.edu        rxDmaState = dmaWriteWaiting;
14137639Sgblack@eecs.umich.edu    else
14147639Sgblack@eecs.umich.edu        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
14157639Sgblack@eecs.umich.edu    return true;
14167435Sgblack@eecs.umich.edu}
14177639Sgblack@eecs.umich.edu
14187639Sgblack@eecs.umich.eduvoid
14197639Sgblack@eecs.umich.eduNSGigE::rxDmaWriteDone()
14207639Sgblack@eecs.umich.edu{
14217639Sgblack@eecs.umich.edu    assert(rxDmaState == dmaWriting);
14227639Sgblack@eecs.umich.edu    rxDmaState = dmaIdle;
14237639Sgblack@eecs.umich.edu
14247435Sgblack@eecs.umich.edu    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
14257639Sgblack@eecs.umich.edu            rxDmaAddr, rxDmaLen);
14267639Sgblack@eecs.umich.edu    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
14277435Sgblack@eecs.umich.edu
14287639Sgblack@eecs.umich.edu    // If the transmit state machine has a pending DMA, let it go first
14297639Sgblack@eecs.umich.edu    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
14307435Sgblack@eecs.umich.edu        txKick();
14317639Sgblack@eecs.umich.edu
14327639Sgblack@eecs.umich.edu    rxKick();
14337435Sgblack@eecs.umich.edu}
14347639Sgblack@eecs.umich.edu
14357639Sgblack@eecs.umich.eduvoid
14367435Sgblack@eecs.umich.eduNSGigE::rxKick()
14377639Sgblack@eecs.umich.edu{
14387639Sgblack@eecs.umich.edu    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
14397435Sgblack@eecs.umich.edu
14407639Sgblack@eecs.umich.edu    DPRINTF(EthernetSM,
14417639Sgblack@eecs.umich.edu            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
14427639Sgblack@eecs.umich.edu            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
14437639Sgblack@eecs.umich.edu
14447435Sgblack@eecs.umich.edu    Addr link, bufptr;
14457639Sgblack@eecs.umich.edu    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
14467639Sgblack@eecs.umich.edu    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
14477435Sgblack@eecs.umich.edu
14487639Sgblack@eecs.umich.edu  next:
14497639Sgblack@eecs.umich.edu    if (clock) {
14507435Sgblack@eecs.umich.edu        if (rxKickTick > curTick) {
14517639Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
14527639Sgblack@eecs.umich.edu                    rxKickTick);
14537435Sgblack@eecs.umich.edu
14547639Sgblack@eecs.umich.edu            goto exit;
14557639Sgblack@eecs.umich.edu        }
14567435Sgblack@eecs.umich.edu
14577435Sgblack@eecs.umich.edu        // Go to the next state machine clock tick.
14587435Sgblack@eecs.umich.edu        rxKickTick = curTick + cycles(1);
14597435Sgblack@eecs.umich.edu    }
14607435Sgblack@eecs.umich.edu
14617435Sgblack@eecs.umich.edu    switch(rxDmaState) {
14627639Sgblack@eecs.umich.edu      case dmaReadWaiting:
14637639Sgblack@eecs.umich.edu        if (doRxDmaRead())
14647639Sgblack@eecs.umich.edu            goto exit;
14657639Sgblack@eecs.umich.edu        break;
14667639Sgblack@eecs.umich.edu      case dmaWriteWaiting:
14677639Sgblack@eecs.umich.edu        if (doRxDmaWrite())
14687639Sgblack@eecs.umich.edu            goto exit;
14697639Sgblack@eecs.umich.edu        break;
14707639Sgblack@eecs.umich.edu      default:
14717639Sgblack@eecs.umich.edu        break;
14727435Sgblack@eecs.umich.edu    }
14737639Sgblack@eecs.umich.edu
14747639Sgblack@eecs.umich.edu    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
14757639Sgblack@eecs.umich.edu    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
14767639Sgblack@eecs.umich.edu
14777639Sgblack@eecs.umich.edu    // see state machine from spec for details
14787639Sgblack@eecs.umich.edu    // the way this works is, if you finish work on one state and can
14797639Sgblack@eecs.umich.edu    // go directly to another, you do that through jumping to the
14807639Sgblack@eecs.umich.edu    // label "next".  however, if you have intermediate work, like DMA
14817639Sgblack@eecs.umich.edu    // so that you can't go to the next state yet, you go to exit and
14827639Sgblack@eecs.umich.edu    // exit the loop.  however, when the DMA is done it will trigger
14837435Sgblack@eecs.umich.edu    // an event and come back to this loop.
14847639Sgblack@eecs.umich.edu    switch (rxState) {
14857639Sgblack@eecs.umich.edu      case rxIdle:
14867639Sgblack@eecs.umich.edu        if (!rxEnable) {
14877639Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
14887639Sgblack@eecs.umich.edu            goto exit;
14897639Sgblack@eecs.umich.edu        }
14907639Sgblack@eecs.umich.edu
14917639Sgblack@eecs.umich.edu        if (CRDD) {
14927639Sgblack@eecs.umich.edu            rxState = rxDescRefr;
14937639Sgblack@eecs.umich.edu
14947435Sgblack@eecs.umich.edu            rxDmaAddr = regs.rxdp & 0x3fffffff;
14957639Sgblack@eecs.umich.edu            rxDmaData =
14967639Sgblack@eecs.umich.edu                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
14977639Sgblack@eecs.umich.edu            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
14987639Sgblack@eecs.umich.edu            rxDmaFree = dmaDescFree;
14997639Sgblack@eecs.umich.edu
15007639Sgblack@eecs.umich.edu            descDmaReads++;
15017639Sgblack@eecs.umich.edu            descDmaRdBytes += rxDmaLen;
15027639Sgblack@eecs.umich.edu
15037639Sgblack@eecs.umich.edu            if (doRxDmaRead())
15047639Sgblack@eecs.umich.edu                goto exit;
15057435Sgblack@eecs.umich.edu        } else {
15067639Sgblack@eecs.umich.edu            rxState = rxDescRead;
15077639Sgblack@eecs.umich.edu
15087639Sgblack@eecs.umich.edu            rxDmaAddr = regs.rxdp & 0x3fffffff;
15097639Sgblack@eecs.umich.edu            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
15107639Sgblack@eecs.umich.edu            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
15117639Sgblack@eecs.umich.edu            rxDmaFree = dmaDescFree;
15127639Sgblack@eecs.umich.edu
15137639Sgblack@eecs.umich.edu            descDmaReads++;
15147639Sgblack@eecs.umich.edu            descDmaRdBytes += rxDmaLen;
15157639Sgblack@eecs.umich.edu
15167435Sgblack@eecs.umich.edu            if (doRxDmaRead())
15177639Sgblack@eecs.umich.edu                goto exit;
15187639Sgblack@eecs.umich.edu        }
15197639Sgblack@eecs.umich.edu        break;
15207639Sgblack@eecs.umich.edu
15217639Sgblack@eecs.umich.edu      case rxDescRefr:
15227639Sgblack@eecs.umich.edu        if (rxDmaState != dmaIdle)
15237639Sgblack@eecs.umich.edu            goto exit;
15247639Sgblack@eecs.umich.edu
15257639Sgblack@eecs.umich.edu        rxState = rxAdvance;
15267435Sgblack@eecs.umich.edu        break;
15277639Sgblack@eecs.umich.edu
15287639Sgblack@eecs.umich.edu     case rxDescRead:
15297639Sgblack@eecs.umich.edu        if (rxDmaState != dmaIdle)
15307639Sgblack@eecs.umich.edu            goto exit;
15317639Sgblack@eecs.umich.edu
15327639Sgblack@eecs.umich.edu        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
15337639Sgblack@eecs.umich.edu                regs.rxdp & 0x3fffffff);
15347639Sgblack@eecs.umich.edu        DPRINTF(EthernetDesc,
15357639Sgblack@eecs.umich.edu                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
15367435Sgblack@eecs.umich.edu                link, bufptr, cmdsts, extsts);
15377435Sgblack@eecs.umich.edu
15387435Sgblack@eecs.umich.edu        if (cmdsts & CMDSTS_OWN) {
15397435Sgblack@eecs.umich.edu            devIntrPost(ISR_RXIDLE);
15407639Sgblack@eecs.umich.edu            rxState = rxIdle;
15417639Sgblack@eecs.umich.edu            goto exit;
15427639Sgblack@eecs.umich.edu        } else {
15437639Sgblack@eecs.umich.edu            rxState = rxFifoBlock;
15447435Sgblack@eecs.umich.edu            rxFragPtr = bufptr;
15457639Sgblack@eecs.umich.edu            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
15467639Sgblack@eecs.umich.edu        }
15477435Sgblack@eecs.umich.edu        break;
15487639Sgblack@eecs.umich.edu
15497639Sgblack@eecs.umich.edu      case rxFifoBlock:
15507435Sgblack@eecs.umich.edu        if (!rxPacket) {
15517639Sgblack@eecs.umich.edu            /**
15527639Sgblack@eecs.umich.edu             * @todo in reality, we should be able to start processing
15537435Sgblack@eecs.umich.edu             * the packet as it arrives, and not have to wait for the
15547435Sgblack@eecs.umich.edu             * full packet ot be in the receive fifo.
15557639Sgblack@eecs.umich.edu             */
15567639Sgblack@eecs.umich.edu            if (rxFifo.empty())
15577435Sgblack@eecs.umich.edu                goto exit;
15587639Sgblack@eecs.umich.edu
15597639Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
15607435Sgblack@eecs.umich.edu
15617435Sgblack@eecs.umich.edu            // If we don't have a packet, grab a new one from the fifo.
15627639Sgblack@eecs.umich.edu            rxPacket = rxFifo.front();
15637639Sgblack@eecs.umich.edu            rxPktBytes = rxPacket->length;
15647639Sgblack@eecs.umich.edu            rxPacketBufPtr = rxPacket->data;
15657639Sgblack@eecs.umich.edu
15667639Sgblack@eecs.umich.edu#if TRACING_ON
15677639Sgblack@eecs.umich.edu            if (DTRACE(Ethernet)) {
15687639Sgblack@eecs.umich.edu                IpPtr ip(rxPacket);
15697435Sgblack@eecs.umich.edu                if (ip) {
15707435Sgblack@eecs.umich.edu                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
15717639Sgblack@eecs.umich.edu                    TcpPtr tcp(ip);
15727639Sgblack@eecs.umich.edu                    if (tcp) {
15737639Sgblack@eecs.umich.edu                        DPRINTF(Ethernet,
15747639Sgblack@eecs.umich.edu                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
15757639Sgblack@eecs.umich.edu                                tcp->sport(), tcp->dport(), tcp->seq(),
15767639Sgblack@eecs.umich.edu                                tcp->ack());
15777639Sgblack@eecs.umich.edu                    }
15787639Sgblack@eecs.umich.edu                }
15797639Sgblack@eecs.umich.edu            }
15807435Sgblack@eecs.umich.edu#endif
15817435Sgblack@eecs.umich.edu
15827435Sgblack@eecs.umich.edu            // sanity check - i think the driver behaves like this
15837435Sgblack@eecs.umich.edu            assert(rxDescCnt >= rxPktBytes);
15847435Sgblack@eecs.umich.edu            rxFifo.pop();
15857435Sgblack@eecs.umich.edu        }
15867639Sgblack@eecs.umich.edu
15877639Sgblack@eecs.umich.edu
15887639Sgblack@eecs.umich.edu        // dont' need the && rxDescCnt > 0 if driver sanity check
15897435Sgblack@eecs.umich.edu        // above holds
15907639Sgblack@eecs.umich.edu        if (rxPktBytes > 0) {
15917639Sgblack@eecs.umich.edu            rxState = rxFragWrite;
15927639Sgblack@eecs.umich.edu            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
15937435Sgblack@eecs.umich.edu            // check holds
15947435Sgblack@eecs.umich.edu            rxXferLen = rxPktBytes;
15957435Sgblack@eecs.umich.edu
15967435Sgblack@eecs.umich.edu            rxDmaAddr = rxFragPtr & 0x3fffffff;
15977435Sgblack@eecs.umich.edu            rxDmaData = rxPacketBufPtr;
15987435Sgblack@eecs.umich.edu            rxDmaLen = rxXferLen;
15997435Sgblack@eecs.umich.edu            rxDmaFree = dmaDataFree;
16007435Sgblack@eecs.umich.edu
16017639Sgblack@eecs.umich.edu            if (doRxDmaWrite())
16027639Sgblack@eecs.umich.edu                goto exit;
16037639Sgblack@eecs.umich.edu
16047639Sgblack@eecs.umich.edu        } else {
16057639Sgblack@eecs.umich.edu            rxState = rxDescWrite;
16067639Sgblack@eecs.umich.edu
16077639Sgblack@eecs.umich.edu            //if (rxPktBytes == 0) {  /* packet is done */
16087639Sgblack@eecs.umich.edu            assert(rxPktBytes == 0);
16097639Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "done with receiving packet\n");
16107639Sgblack@eecs.umich.edu
16117639Sgblack@eecs.umich.edu            cmdsts |= CMDSTS_OWN;
16127639Sgblack@eecs.umich.edu            cmdsts &= ~CMDSTS_MORE;
16137639Sgblack@eecs.umich.edu            cmdsts |= CMDSTS_OK;
16147639Sgblack@eecs.umich.edu            cmdsts &= 0xffff0000;
16157639Sgblack@eecs.umich.edu            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
16167639Sgblack@eecs.umich.edu
16177639Sgblack@eecs.umich.edu#if 0
16187639Sgblack@eecs.umich.edu            /*
16197639Sgblack@eecs.umich.edu             * all the driver uses these are for its own stats keeping
16207639Sgblack@eecs.umich.edu             * which we don't care about, aren't necessary for
16217639Sgblack@eecs.umich.edu             * functionality and doing this would just slow us down.
16227639Sgblack@eecs.umich.edu             * if they end up using this in a later version for
16237639Sgblack@eecs.umich.edu             * functional purposes, just undef
16247639Sgblack@eecs.umich.edu             */
16257639Sgblack@eecs.umich.edu            if (rxFilterEnable) {
16267639Sgblack@eecs.umich.edu                cmdsts &= ~CMDSTS_DEST_MASK;
16277639Sgblack@eecs.umich.edu                const EthAddr &dst = rxFifoFront()->dst();
16287639Sgblack@eecs.umich.edu                if (dst->unicast())
16297639Sgblack@eecs.umich.edu                    cmdsts |= CMDSTS_DEST_SELF;
16307639Sgblack@eecs.umich.edu                if (dst->multicast())
16317639Sgblack@eecs.umich.edu                    cmdsts |= CMDSTS_DEST_MULTI;
16327639Sgblack@eecs.umich.edu                if (dst->broadcast())
16337639Sgblack@eecs.umich.edu                    cmdsts |= CMDSTS_DEST_MASK;
16347639Sgblack@eecs.umich.edu            }
16357639Sgblack@eecs.umich.edu#endif
16367639Sgblack@eecs.umich.edu
16377639Sgblack@eecs.umich.edu            IpPtr ip(rxPacket);
16387639Sgblack@eecs.umich.edu            if (extstsEnable && ip) {
16397639Sgblack@eecs.umich.edu                extsts |= EXTSTS_IPPKT;
16407639Sgblack@eecs.umich.edu                rxIpChecksums++;
16417639Sgblack@eecs.umich.edu                if (cksum(ip) != 0) {
16427435Sgblack@eecs.umich.edu                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
16437639Sgblack@eecs.umich.edu                    extsts |= EXTSTS_IPERR;
16447639Sgblack@eecs.umich.edu                }
16457639Sgblack@eecs.umich.edu                TcpPtr tcp(ip);
16467639Sgblack@eecs.umich.edu                UdpPtr udp(ip);
16477639Sgblack@eecs.umich.edu                if (tcp) {
16487639Sgblack@eecs.umich.edu                    extsts |= EXTSTS_TCPPKT;
16497639Sgblack@eecs.umich.edu                    rxTcpChecksums++;
16507639Sgblack@eecs.umich.edu                    if (cksum(tcp) != 0) {
16517639Sgblack@eecs.umich.edu                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
16527639Sgblack@eecs.umich.edu                        extsts |= EXTSTS_TCPERR;
16537639Sgblack@eecs.umich.edu
16547639Sgblack@eecs.umich.edu                    }
16557639Sgblack@eecs.umich.edu                } else if (udp) {
16567435Sgblack@eecs.umich.edu                    extsts |= EXTSTS_UDPPKT;
16577639Sgblack@eecs.umich.edu                    rxUdpChecksums++;
16587639Sgblack@eecs.umich.edu                    if (cksum(udp) != 0) {
16597639Sgblack@eecs.umich.edu                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
16607639Sgblack@eecs.umich.edu                        extsts |= EXTSTS_UDPERR;
16617639Sgblack@eecs.umich.edu                    }
16627639Sgblack@eecs.umich.edu                }
16637639Sgblack@eecs.umich.edu            }
16647639Sgblack@eecs.umich.edu            rxPacket = 0;
16657639Sgblack@eecs.umich.edu
16667639Sgblack@eecs.umich.edu            /*
16677639Sgblack@eecs.umich.edu             * the driver seems to always receive into desc buffers
16687639Sgblack@eecs.umich.edu             * of size 1514, so you never have a pkt that is split
16697639Sgblack@eecs.umich.edu             * into multiple descriptors on the receive side, so
16707435Sgblack@eecs.umich.edu             * i don't implement that case, hence the assert above.
16717435Sgblack@eecs.umich.edu             */
16727435Sgblack@eecs.umich.edu
16737435Sgblack@eecs.umich.edu            DPRINTF(EthernetDesc,
16747435Sgblack@eecs.umich.edu                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
16757435Sgblack@eecs.umich.edu                    regs.rxdp & 0x3fffffff);
16767435Sgblack@eecs.umich.edu            DPRINTF(EthernetDesc,
16777435Sgblack@eecs.umich.edu                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
16787435Sgblack@eecs.umich.edu                    link, bufptr, cmdsts, extsts);
16797435Sgblack@eecs.umich.edu
16807435Sgblack@eecs.umich.edu            rxDmaAddr = regs.rxdp & 0x3fffffff;
16817435Sgblack@eecs.umich.edu            rxDmaData = &cmdsts;
16827435Sgblack@eecs.umich.edu            if (is64bit) {
16837435Sgblack@eecs.umich.edu                rxDmaAddr += offsetof(ns_desc64, cmdsts);
16847435Sgblack@eecs.umich.edu                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
16857435Sgblack@eecs.umich.edu            } else {
16867435Sgblack@eecs.umich.edu                rxDmaAddr += offsetof(ns_desc32, cmdsts);
16877435Sgblack@eecs.umich.edu                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
16887435Sgblack@eecs.umich.edu            }
16897435Sgblack@eecs.umich.edu            rxDmaFree = dmaDescFree;
16907435Sgblack@eecs.umich.edu
16917435Sgblack@eecs.umich.edu            descDmaWrites++;
16927435Sgblack@eecs.umich.edu            descDmaWrBytes += rxDmaLen;
16937435Sgblack@eecs.umich.edu
16947639Sgblack@eecs.umich.edu            if (doRxDmaWrite())
16957639Sgblack@eecs.umich.edu                goto exit;
16967435Sgblack@eecs.umich.edu        }
16977639Sgblack@eecs.umich.edu        break;
16987435Sgblack@eecs.umich.edu
16997435Sgblack@eecs.umich.edu      case rxFragWrite:
17007435Sgblack@eecs.umich.edu        if (rxDmaState != dmaIdle)
17017639Sgblack@eecs.umich.edu            goto exit;
17027639Sgblack@eecs.umich.edu
17037639Sgblack@eecs.umich.edu        rxPacketBufPtr += rxXferLen;
17047639Sgblack@eecs.umich.edu        rxFragPtr += rxXferLen;
17057639Sgblack@eecs.umich.edu        rxPktBytes -= rxXferLen;
17067639Sgblack@eecs.umich.edu
17077639Sgblack@eecs.umich.edu        rxState = rxFifoBlock;
17087639Sgblack@eecs.umich.edu        break;
17097639Sgblack@eecs.umich.edu
17107435Sgblack@eecs.umich.edu      case rxDescWrite:
17117435Sgblack@eecs.umich.edu        if (rxDmaState != dmaIdle)
17127639Sgblack@eecs.umich.edu            goto exit;
17137639Sgblack@eecs.umich.edu
17147639Sgblack@eecs.umich.edu        assert(cmdsts & CMDSTS_OWN);
17157639Sgblack@eecs.umich.edu
17167639Sgblack@eecs.umich.edu        assert(rxPacket == 0);
17177639Sgblack@eecs.umich.edu        devIntrPost(ISR_RXOK);
17187639Sgblack@eecs.umich.edu
17197639Sgblack@eecs.umich.edu        if (cmdsts & CMDSTS_INTR)
17207639Sgblack@eecs.umich.edu            devIntrPost(ISR_RXDESC);
17217435Sgblack@eecs.umich.edu
17227435Sgblack@eecs.umich.edu        if (!rxEnable) {
17237435Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "Halting the RX state machine\n");
17247435Sgblack@eecs.umich.edu            rxState = rxIdle;
17257639Sgblack@eecs.umich.edu            goto exit;
17267639Sgblack@eecs.umich.edu        } else
17277639Sgblack@eecs.umich.edu            rxState = rxAdvance;
17287435Sgblack@eecs.umich.edu        break;
17297639Sgblack@eecs.umich.edu
17307639Sgblack@eecs.umich.edu      case rxAdvance:
17317639Sgblack@eecs.umich.edu        if (link == 0) {
17327639Sgblack@eecs.umich.edu            devIntrPost(ISR_RXIDLE);
17337639Sgblack@eecs.umich.edu            rxState = rxIdle;
17347639Sgblack@eecs.umich.edu            CRDD = true;
17357639Sgblack@eecs.umich.edu            goto exit;
17367639Sgblack@eecs.umich.edu        } else {
17377639Sgblack@eecs.umich.edu            if (rxDmaState != dmaIdle)
17387639Sgblack@eecs.umich.edu                goto exit;
17397435Sgblack@eecs.umich.edu            rxState = rxDescRead;
17407639Sgblack@eecs.umich.edu            regs.rxdp = link;
17417639Sgblack@eecs.umich.edu            CRDD = false;
17427639Sgblack@eecs.umich.edu
17437639Sgblack@eecs.umich.edu            rxDmaAddr = regs.rxdp & 0x3fffffff;
17447639Sgblack@eecs.umich.edu            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
17457639Sgblack@eecs.umich.edu            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
17467639Sgblack@eecs.umich.edu            rxDmaFree = dmaDescFree;
17477639Sgblack@eecs.umich.edu
17487639Sgblack@eecs.umich.edu            if (doRxDmaRead())
17497639Sgblack@eecs.umich.edu                goto exit;
17507435Sgblack@eecs.umich.edu        }
17517435Sgblack@eecs.umich.edu        break;
17527639Sgblack@eecs.umich.edu
17537639Sgblack@eecs.umich.edu      default:
17547639Sgblack@eecs.umich.edu        panic("Invalid rxState!");
17557639Sgblack@eecs.umich.edu    }
17567639Sgblack@eecs.umich.edu
17577639Sgblack@eecs.umich.edu    DPRINTF(EthernetSM, "entering next rxState=%s\n",
17587639Sgblack@eecs.umich.edu            NsRxStateStrings[rxState]);
17597639Sgblack@eecs.umich.edu    goto next;
17607639Sgblack@eecs.umich.edu
17617639Sgblack@eecs.umich.edu  exit:
17627639Sgblack@eecs.umich.edu    /**
17637639Sgblack@eecs.umich.edu     * @todo do we want to schedule a future kick?
17647435Sgblack@eecs.umich.edu     */
17657435Sgblack@eecs.umich.edu    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
17667435Sgblack@eecs.umich.edu            NsRxStateStrings[rxState]);
17677435Sgblack@eecs.umich.edu
17687435Sgblack@eecs.umich.edu    if (clock && !rxKickEvent.scheduled())
17697435Sgblack@eecs.umich.edu        rxKickEvent.schedule(rxKickTick);
17707435Sgblack@eecs.umich.edu}
17717435Sgblack@eecs.umich.edu
17727435Sgblack@eecs.umich.eduvoid
17737435Sgblack@eecs.umich.eduNSGigE::transmit()
17747435Sgblack@eecs.umich.edu{
17757435Sgblack@eecs.umich.edu    if (txFifo.empty()) {
17767435Sgblack@eecs.umich.edu        DPRINTF(Ethernet, "nothing to transmit\n");
17777435Sgblack@eecs.umich.edu        return;
17787435Sgblack@eecs.umich.edu    }
17797639Sgblack@eecs.umich.edu
17807435Sgblack@eecs.umich.edu    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
17817435Sgblack@eecs.umich.edu            txFifo.size());
17827435Sgblack@eecs.umich.edu    if (interface->sendPacket(txFifo.front())) {
17837435Sgblack@eecs.umich.edu#if TRACING_ON
17847435Sgblack@eecs.umich.edu        if (DTRACE(Ethernet)) {
17857435Sgblack@eecs.umich.edu            IpPtr ip(txFifo.front());
17867356Sgblack@eecs.umich.edu            if (ip) {
17877356Sgblack@eecs.umich.edu                DPRINTF(Ethernet, "ID is %d\n", ip->id());
17887356Sgblack@eecs.umich.edu                TcpPtr tcp(ip);
17897356Sgblack@eecs.umich.edu                if (tcp) {
17907356Sgblack@eecs.umich.edu                    DPRINTF(Ethernet,
17917178Sgblack@eecs.umich.edu                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
17927178Sgblack@eecs.umich.edu                            tcp->sport(), tcp->dport(), tcp->seq(),
17937178Sgblack@eecs.umich.edu                            tcp->ack());
17947337Sgblack@eecs.umich.edu                }
17957178Sgblack@eecs.umich.edu            }
17967178Sgblack@eecs.umich.edu        }
17977178Sgblack@eecs.umich.edu#endif
17987178Sgblack@eecs.umich.edu
17997178Sgblack@eecs.umich.edu        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
18007178Sgblack@eecs.umich.edu        txBytes += txFifo.front()->length;
18017178Sgblack@eecs.umich.edu        txPackets++;
18027178Sgblack@eecs.umich.edu
18037178Sgblack@eecs.umich.edu        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
18047178Sgblack@eecs.umich.edu                txFifo.avail());
18057178Sgblack@eecs.umich.edu        txFifo.pop();
18067335Sgblack@eecs.umich.edu
18077335Sgblack@eecs.umich.edu        /*
18087335Sgblack@eecs.umich.edu         * normally do a writeback of the descriptor here, and ONLY
18097335Sgblack@eecs.umich.edu         * after that is done, send this interrupt.  but since our
18107335Sgblack@eecs.umich.edu         * stuff never actually fails, just do this interrupt here,
18117335Sgblack@eecs.umich.edu         * otherwise the code has to stray from this nice format.
18127335Sgblack@eecs.umich.edu         * besides, it's functionally the same.
18137335Sgblack@eecs.umich.edu         */
18147335Sgblack@eecs.umich.edu        devIntrPost(ISR_TXOK);
18157335Sgblack@eecs.umich.edu    }
18167335Sgblack@eecs.umich.edu
18177335Sgblack@eecs.umich.edu   if (!txFifo.empty() && !txEvent.scheduled()) {
18187337Sgblack@eecs.umich.edu       DPRINTF(Ethernet, "reschedule transmit\n");
18197335Sgblack@eecs.umich.edu       txEvent.schedule(curTick + retryTime);
18207335Sgblack@eecs.umich.edu   }
18217335Sgblack@eecs.umich.edu}
18227335Sgblack@eecs.umich.edu
18237335Sgblack@eecs.umich.edubool
18247335Sgblack@eecs.umich.eduNSGigE::doTxDmaRead()
18257335Sgblack@eecs.umich.edu{
18267335Sgblack@eecs.umich.edu    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
18277335Sgblack@eecs.umich.edu    txDmaState = dmaReading;
18287335Sgblack@eecs.umich.edu
18297335Sgblack@eecs.umich.edu    if (dmaPending())
18307335Sgblack@eecs.umich.edu        txDmaState = dmaReadWaiting;
18317178Sgblack@eecs.umich.edu    else
18327178Sgblack@eecs.umich.edu        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
18337178Sgblack@eecs.umich.edu
18347413Sgblack@eecs.umich.edu    return true;
18357639Sgblack@eecs.umich.edu}
18367413Sgblack@eecs.umich.edu
18377413Sgblack@eecs.umich.eduvoid
18387413Sgblack@eecs.umich.eduNSGigE::txDmaReadDone()
18397413Sgblack@eecs.umich.edu{
18407413Sgblack@eecs.umich.edu    assert(txDmaState == dmaReading);
18417413Sgblack@eecs.umich.edu    txDmaState = dmaIdle;
18427413Sgblack@eecs.umich.edu
18437413Sgblack@eecs.umich.edu    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
18447413Sgblack@eecs.umich.edu            txDmaAddr, txDmaLen);
18457413Sgblack@eecs.umich.edu    DDUMP(EthernetDMA, txDmaData, txDmaLen);
18467413Sgblack@eecs.umich.edu
18477413Sgblack@eecs.umich.edu    // If the receive state machine  has a pending DMA, let it go first
18487413Sgblack@eecs.umich.edu    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
18497413Sgblack@eecs.umich.edu        rxKick();
18507413Sgblack@eecs.umich.edu
18517413Sgblack@eecs.umich.edu    txKick();
18527413Sgblack@eecs.umich.edu}
18537178Sgblack@eecs.umich.edu
18547178Sgblack@eecs.umich.edubool
18557178Sgblack@eecs.umich.eduNSGigE::doTxDmaWrite()
18567178Sgblack@eecs.umich.edu{
18577178Sgblack@eecs.umich.edu    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
18587178Sgblack@eecs.umich.edu    txDmaState = dmaWriting;
18597178Sgblack@eecs.umich.edu
18607178Sgblack@eecs.umich.edu    if (dmaPending())
18617178Sgblack@eecs.umich.edu        txDmaState = dmaWriteWaiting;
18627178Sgblack@eecs.umich.edu    else
18637178Sgblack@eecs.umich.edu        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
18647178Sgblack@eecs.umich.edu    return true;
18657346Sgblack@eecs.umich.edu}
18667346Sgblack@eecs.umich.edu
18677346Sgblack@eecs.umich.eduvoid
18687346Sgblack@eecs.umich.eduNSGigE::txDmaWriteDone()
18697346Sgblack@eecs.umich.edu{
18707346Sgblack@eecs.umich.edu    assert(txDmaState == dmaWriting);
18717346Sgblack@eecs.umich.edu    txDmaState = dmaIdle;
18727346Sgblack@eecs.umich.edu
18737346Sgblack@eecs.umich.edu    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
18747346Sgblack@eecs.umich.edu            txDmaAddr, txDmaLen);
18757178Sgblack@eecs.umich.edu    DDUMP(EthernetDMA, txDmaData, txDmaLen);
18767346Sgblack@eecs.umich.edu
18777346Sgblack@eecs.umich.edu    // If the receive state machine  has a pending DMA, let it go first
18787346Sgblack@eecs.umich.edu    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
18797346Sgblack@eecs.umich.edu        rxKick();
18807346Sgblack@eecs.umich.edu
18817346Sgblack@eecs.umich.edu    txKick();
18827346Sgblack@eecs.umich.edu}
18837346Sgblack@eecs.umich.edu
18847346Sgblack@eecs.umich.eduvoid
18857346Sgblack@eecs.umich.eduNSGigE::txKick()
18867346Sgblack@eecs.umich.edu{
18877346Sgblack@eecs.umich.edu    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
18887346Sgblack@eecs.umich.edu
18897346Sgblack@eecs.umich.edu    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
18907346Sgblack@eecs.umich.edu            NsTxStateStrings[txState], is64bit ? 64 : 32);
18917178Sgblack@eecs.umich.edu
18927337Sgblack@eecs.umich.edu    Addr link, bufptr;
18937337Sgblack@eecs.umich.edu    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
18947337Sgblack@eecs.umich.edu    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
18957337Sgblack@eecs.umich.edu
18967337Sgblack@eecs.umich.edu  next:
18977337Sgblack@eecs.umich.edu    if (clock) {
18987337Sgblack@eecs.umich.edu        if (txKickTick > curTick) {
18997337Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
19007337Sgblack@eecs.umich.edu                    txKickTick);
19017337Sgblack@eecs.umich.edu            goto exit;
19027337Sgblack@eecs.umich.edu        }
19037337Sgblack@eecs.umich.edu
19047337Sgblack@eecs.umich.edu        // Go to the next state machine clock tick.
19057337Sgblack@eecs.umich.edu        txKickTick = curTick + cycles(1);
19067337Sgblack@eecs.umich.edu    }
19077178Sgblack@eecs.umich.edu
19087178Sgblack@eecs.umich.edu    switch(txDmaState) {
19097178Sgblack@eecs.umich.edu      case dmaReadWaiting:
19107178Sgblack@eecs.umich.edu        if (doTxDmaRead())
19117337Sgblack@eecs.umich.edu            goto exit;
19127337Sgblack@eecs.umich.edu        break;
19137337Sgblack@eecs.umich.edu      case dmaWriteWaiting:
19147337Sgblack@eecs.umich.edu        if (doTxDmaWrite())
19157346Sgblack@eecs.umich.edu            goto exit;
19167346Sgblack@eecs.umich.edu        break;
19177346Sgblack@eecs.umich.edu      default:
19187346Sgblack@eecs.umich.edu        break;
19197346Sgblack@eecs.umich.edu    }
19207337Sgblack@eecs.umich.edu
19217178Sgblack@eecs.umich.edu    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
19227321Sgblack@eecs.umich.edu    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
19237356Sgblack@eecs.umich.edu    switch (txState) {
19247321Sgblack@eecs.umich.edu      case txIdle:
19257356Sgblack@eecs.umich.edu        if (!txEnable) {
19267356Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
19277356Sgblack@eecs.umich.edu            goto exit;
19287356Sgblack@eecs.umich.edu        }
19297356Sgblack@eecs.umich.edu
19307356Sgblack@eecs.umich.edu        if (CTDD) {
19317356Sgblack@eecs.umich.edu            txState = txDescRefr;
19327356Sgblack@eecs.umich.edu
19337356Sgblack@eecs.umich.edu            txDmaAddr = regs.txdp & 0x3fffffff;
19347356Sgblack@eecs.umich.edu            txDmaData =
19357356Sgblack@eecs.umich.edu                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
19367356Sgblack@eecs.umich.edu            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
19377321Sgblack@eecs.umich.edu            txDmaFree = dmaDescFree;
19387321Sgblack@eecs.umich.edu
19397321Sgblack@eecs.umich.edu            descDmaReads++;
19407321Sgblack@eecs.umich.edu            descDmaRdBytes += txDmaLen;
19417321Sgblack@eecs.umich.edu
19427321Sgblack@eecs.umich.edu            if (doTxDmaRead())
19437321Sgblack@eecs.umich.edu                goto exit;
19447321Sgblack@eecs.umich.edu
19457321Sgblack@eecs.umich.edu        } else {
19467321Sgblack@eecs.umich.edu            txState = txDescRead;
19477321Sgblack@eecs.umich.edu
19487335Sgblack@eecs.umich.edu            txDmaAddr = regs.txdp & 0x3fffffff;
19497335Sgblack@eecs.umich.edu            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
19507335Sgblack@eecs.umich.edu            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
19517335Sgblack@eecs.umich.edu            txDmaFree = dmaDescFree;
19527335Sgblack@eecs.umich.edu
19537335Sgblack@eecs.umich.edu            descDmaReads++;
19547335Sgblack@eecs.umich.edu            descDmaRdBytes += txDmaLen;
19557335Sgblack@eecs.umich.edu
19567335Sgblack@eecs.umich.edu            if (doTxDmaRead())
19577321Sgblack@eecs.umich.edu                goto exit;
19587323Sgblack@eecs.umich.edu        }
19597323Sgblack@eecs.umich.edu        break;
19607323Sgblack@eecs.umich.edu
19617323Sgblack@eecs.umich.edu      case txDescRefr:
19627323Sgblack@eecs.umich.edu        if (txDmaState != dmaIdle)
19637323Sgblack@eecs.umich.edu            goto exit;
19647323Sgblack@eecs.umich.edu
19657323Sgblack@eecs.umich.edu        txState = txAdvance;
19667323Sgblack@eecs.umich.edu        break;
19677323Sgblack@eecs.umich.edu
19687394Sgblack@eecs.umich.edu      case txDescRead:
19697394Sgblack@eecs.umich.edu        if (txDmaState != dmaIdle)
19707394Sgblack@eecs.umich.edu            goto exit;
19717394Sgblack@eecs.umich.edu
19727394Sgblack@eecs.umich.edu        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
19737394Sgblack@eecs.umich.edu                regs.txdp & 0x3fffffff);
19747323Sgblack@eecs.umich.edu        DPRINTF(EthernetDesc,
19757323Sgblack@eecs.umich.edu                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
19767323Sgblack@eecs.umich.edu                link, bufptr, cmdsts, extsts);
19777323Sgblack@eecs.umich.edu
19787323Sgblack@eecs.umich.edu        if (cmdsts & CMDSTS_OWN) {
19797323Sgblack@eecs.umich.edu            txState = txFifoBlock;
19807643Sgblack@eecs.umich.edu            txFragPtr = bufptr;
19817643Sgblack@eecs.umich.edu            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
19827643Sgblack@eecs.umich.edu        } else {
19837643Sgblack@eecs.umich.edu            devIntrPost(ISR_TXIDLE);
19847643Sgblack@eecs.umich.edu            txState = txIdle;
19857321Sgblack@eecs.umich.edu            goto exit;
19867321Sgblack@eecs.umich.edu        }
19877321Sgblack@eecs.umich.edu        break;
19887335Sgblack@eecs.umich.edu
19897335Sgblack@eecs.umich.edu      case txFifoBlock:
19907639Sgblack@eecs.umich.edu        if (!txPacket) {
19917639Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
19927335Sgblack@eecs.umich.edu            txPacket = new EthPacketData(16384);
19937335Sgblack@eecs.umich.edu            txPacketBufPtr = txPacket->data;
19947335Sgblack@eecs.umich.edu        }
19957639Sgblack@eecs.umich.edu
19967639Sgblack@eecs.umich.edu        if (txDescCnt == 0) {
19977335Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
19987639Sgblack@eecs.umich.edu            if (cmdsts & CMDSTS_MORE) {
19997639Sgblack@eecs.umich.edu                DPRINTF(EthernetSM, "there are more descriptors to come\n");
20007335Sgblack@eecs.umich.edu                txState = txDescWrite;
20017639Sgblack@eecs.umich.edu
20027335Sgblack@eecs.umich.edu                cmdsts &= ~CMDSTS_OWN;
20037335Sgblack@eecs.umich.edu
20047335Sgblack@eecs.umich.edu                txDmaAddr = regs.txdp & 0x3fffffff;
20057639Sgblack@eecs.umich.edu                txDmaData = &cmdsts;
20067639Sgblack@eecs.umich.edu                if (is64bit) {
20077639Sgblack@eecs.umich.edu                    txDmaAddr += offsetof(ns_desc64, cmdsts);
20087639Sgblack@eecs.umich.edu                    txDmaLen = sizeof(txDesc64.cmdsts);
20097639Sgblack@eecs.umich.edu                } else {
20107639Sgblack@eecs.umich.edu                    txDmaAddr += offsetof(ns_desc32, cmdsts);
20117639Sgblack@eecs.umich.edu                    txDmaLen = sizeof(txDesc32.cmdsts);
20127639Sgblack@eecs.umich.edu                }
20137639Sgblack@eecs.umich.edu                txDmaFree = dmaDescFree;
20147639Sgblack@eecs.umich.edu
20157639Sgblack@eecs.umich.edu                if (doTxDmaWrite())
20167639Sgblack@eecs.umich.edu                    goto exit;
20177639Sgblack@eecs.umich.edu
20187639Sgblack@eecs.umich.edu            } else { /* this packet is totally done */
20197639Sgblack@eecs.umich.edu                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
20207639Sgblack@eecs.umich.edu                /* deal with the the packet that just finished */
20217639Sgblack@eecs.umich.edu                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
20227639Sgblack@eecs.umich.edu                    IpPtr ip(txPacket);
20237639Sgblack@eecs.umich.edu                    if (extsts & EXTSTS_UDPPKT) {
20247639Sgblack@eecs.umich.edu                        UdpPtr udp(ip);
20257639Sgblack@eecs.umich.edu                        udp->sum(0);
20267639Sgblack@eecs.umich.edu                        udp->sum(cksum(udp));
20277639Sgblack@eecs.umich.edu                        txUdpChecksums++;
20287639Sgblack@eecs.umich.edu                    } else if (extsts & EXTSTS_TCPPKT) {
20297639Sgblack@eecs.umich.edu                        TcpPtr tcp(ip);
20307639Sgblack@eecs.umich.edu                        tcp->sum(0);
20317639Sgblack@eecs.umich.edu                        tcp->sum(cksum(tcp));
20327639Sgblack@eecs.umich.edu                        txTcpChecksums++;
20337639Sgblack@eecs.umich.edu                    }
20347335Sgblack@eecs.umich.edu                    if (extsts & EXTSTS_IPPKT) {
20357321Sgblack@eecs.umich.edu                        ip->sum(0);
20367321Sgblack@eecs.umich.edu                        ip->sum(cksum(ip));
20377321Sgblack@eecs.umich.edu                        txIpChecksums++;
20387335Sgblack@eecs.umich.edu                    }
20397335Sgblack@eecs.umich.edu                }
20407335Sgblack@eecs.umich.edu
20417335Sgblack@eecs.umich.edu                txPacket->length = txPacketBufPtr - txPacket->data;
20427335Sgblack@eecs.umich.edu                // this is just because the receive can't handle a
20437335Sgblack@eecs.umich.edu                // packet bigger want to make sure
20447335Sgblack@eecs.umich.edu                if (txPacket->length > 1514)
20457335Sgblack@eecs.umich.edu                    panic("transmit packet too large, %s > 1514\n",
20467335Sgblack@eecs.umich.edu                          txPacket->length);
20477321Sgblack@eecs.umich.edu
20487326Sgblack@eecs.umich.edu#ifndef NDEBUG
20497326Sgblack@eecs.umich.edu                bool success =
20507326Sgblack@eecs.umich.edu#endif
20517326Sgblack@eecs.umich.edu                    txFifo.push(txPacket);
20527326Sgblack@eecs.umich.edu                assert(success);
20537326Sgblack@eecs.umich.edu
20547326Sgblack@eecs.umich.edu                /*
20557326Sgblack@eecs.umich.edu                 * this following section is not tqo spec, but
20567326Sgblack@eecs.umich.edu                 * functionally shouldn't be any different.  normally,
20577326Sgblack@eecs.umich.edu                 * the chip will wait til the transmit has occurred
20587326Sgblack@eecs.umich.edu                 * before writing back the descriptor because it has
20597326Sgblack@eecs.umich.edu                 * to wait to see that it was successfully transmitted
20607326Sgblack@eecs.umich.edu                 * to decide whether to set CMDSTS_OK or not.
20617326Sgblack@eecs.umich.edu                 * however, in the simulator since it is always
20627326Sgblack@eecs.umich.edu                 * successfully transmitted, and writing it exactly to
20637326Sgblack@eecs.umich.edu                 * spec would complicate the code, we just do it here
20647326Sgblack@eecs.umich.edu                 */
20657326Sgblack@eecs.umich.edu
20667326Sgblack@eecs.umich.edu                cmdsts &= ~CMDSTS_OWN;
20677326Sgblack@eecs.umich.edu                cmdsts |= CMDSTS_OK;
20687326Sgblack@eecs.umich.edu
20697326Sgblack@eecs.umich.edu                DPRINTF(EthernetDesc,
20707392Sgblack@eecs.umich.edu                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
20717392Sgblack@eecs.umich.edu                        cmdsts, extsts);
20727392Sgblack@eecs.umich.edu
20737392Sgblack@eecs.umich.edu                txDmaFree = dmaDescFree;
20747392Sgblack@eecs.umich.edu                txDmaAddr = regs.txdp & 0x3fffffff;
20757392Sgblack@eecs.umich.edu                txDmaData = &cmdsts;
20767643Sgblack@eecs.umich.edu                if (is64bit) {
20777643Sgblack@eecs.umich.edu                    txDmaAddr += offsetof(ns_desc64, cmdsts);
20787643Sgblack@eecs.umich.edu                    txDmaLen =
20797643Sgblack@eecs.umich.edu                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
20807643Sgblack@eecs.umich.edu                } else {
20817643Sgblack@eecs.umich.edu                    txDmaAddr += offsetof(ns_desc32, cmdsts);
20827643Sgblack@eecs.umich.edu                    txDmaLen =
20837643Sgblack@eecs.umich.edu                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
20847643Sgblack@eecs.umich.edu                }
20857392Sgblack@eecs.umich.edu
20867392Sgblack@eecs.umich.edu                descDmaWrites++;
20877392Sgblack@eecs.umich.edu                descDmaWrBytes += txDmaLen;
20887321Sgblack@eecs.umich.edu
20897321Sgblack@eecs.umich.edu                transmit();
20907335Sgblack@eecs.umich.edu                txPacket = 0;
20917335Sgblack@eecs.umich.edu
20927639Sgblack@eecs.umich.edu                if (!txEnable) {
20937639Sgblack@eecs.umich.edu                    DPRINTF(EthernetSM, "halting TX state machine\n");
20947639Sgblack@eecs.umich.edu                    txState = txIdle;
20957335Sgblack@eecs.umich.edu                    goto exit;
20967335Sgblack@eecs.umich.edu                } else
20977335Sgblack@eecs.umich.edu                    txState = txAdvance;
20987335Sgblack@eecs.umich.edu
20997639Sgblack@eecs.umich.edu                if (doTxDmaWrite())
21007335Sgblack@eecs.umich.edu                    goto exit;
21017335Sgblack@eecs.umich.edu            }
21027335Sgblack@eecs.umich.edu        } else {
21037335Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
21047335Sgblack@eecs.umich.edu            if (!txFifo.full()) {
21057335Sgblack@eecs.umich.edu                txState = txFragRead;
21067335Sgblack@eecs.umich.edu
21077639Sgblack@eecs.umich.edu                /*
21087639Sgblack@eecs.umich.edu                 * The number of bytes transferred is either whatever
21097335Sgblack@eecs.umich.edu                 * is left in the descriptor (txDescCnt), or if there
21107335Sgblack@eecs.umich.edu                 * is not enough room in the fifo, just whatever room
21117335Sgblack@eecs.umich.edu                 * is left in the fifo
21127335Sgblack@eecs.umich.edu                 */
21137335Sgblack@eecs.umich.edu                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
21147335Sgblack@eecs.umich.edu
21157335Sgblack@eecs.umich.edu                txDmaAddr = txFragPtr & 0x3fffffff;
21167639Sgblack@eecs.umich.edu                txDmaData = txPacketBufPtr;
21177335Sgblack@eecs.umich.edu                txDmaLen = txXferLen;
21187639Sgblack@eecs.umich.edu                txDmaFree = dmaDataFree;
21197639Sgblack@eecs.umich.edu
21207335Sgblack@eecs.umich.edu                if (doTxDmaRead())
21217321Sgblack@eecs.umich.edu                    goto exit;
21227321Sgblack@eecs.umich.edu            } else {
21237321Sgblack@eecs.umich.edu                txState = txFifoBlock;
21247321Sgblack@eecs.umich.edu                transmit();
21257321Sgblack@eecs.umich.edu
21267356Sgblack@eecs.umich.edu                goto exit;
21277356Sgblack@eecs.umich.edu            }
21287356Sgblack@eecs.umich.edu
21297356Sgblack@eecs.umich.edu        }
21307356Sgblack@eecs.umich.edu        break;
21317356Sgblack@eecs.umich.edu
21327363Sgblack@eecs.umich.edu      case txFragRead:
21337363Sgblack@eecs.umich.edu        if (txDmaState != dmaIdle)
21347363Sgblack@eecs.umich.edu            goto exit;
21357363Sgblack@eecs.umich.edu
21367363Sgblack@eecs.umich.edu        txPacketBufPtr += txXferLen;
21377363Sgblack@eecs.umich.edu        txFragPtr += txXferLen;
21387363Sgblack@eecs.umich.edu        txDescCnt -= txXferLen;
21397363Sgblack@eecs.umich.edu        txFifo.reserve(txXferLen);
21407363Sgblack@eecs.umich.edu
21417363Sgblack@eecs.umich.edu        txState = txFifoBlock;
21427363Sgblack@eecs.umich.edu        break;
21437363Sgblack@eecs.umich.edu
21447363Sgblack@eecs.umich.edu      case txDescWrite:
21457363Sgblack@eecs.umich.edu        if (txDmaState != dmaIdle)
21467372Sgblack@eecs.umich.edu            goto exit;
21477389Sgblack@eecs.umich.edu
21487389Sgblack@eecs.umich.edu        if (cmdsts & CMDSTS_INTR)
21497372Sgblack@eecs.umich.edu            devIntrPost(ISR_TXDESC);
21507372Sgblack@eecs.umich.edu
21517372Sgblack@eecs.umich.edu        if (!txEnable) {
21527372Sgblack@eecs.umich.edu            DPRINTF(EthernetSM, "halting TX state machine\n");
21537372Sgblack@eecs.umich.edu            txState = txIdle;
21547372Sgblack@eecs.umich.edu            goto exit;
21557372Sgblack@eecs.umich.edu        } else
21567372Sgblack@eecs.umich.edu            txState = txAdvance;
21577372Sgblack@eecs.umich.edu        break;
21587372Sgblack@eecs.umich.edu
21597372Sgblack@eecs.umich.edu      case txAdvance:
21607372Sgblack@eecs.umich.edu        if (link == 0) {
21617372Sgblack@eecs.umich.edu            devIntrPost(ISR_TXIDLE);
21627372Sgblack@eecs.umich.edu            txState = txIdle;
21637372Sgblack@eecs.umich.edu            goto exit;
21647372Sgblack@eecs.umich.edu        } else {
21657372Sgblack@eecs.umich.edu            if (txDmaState != dmaIdle)
21667372Sgblack@eecs.umich.edu                goto exit;
21677363Sgblack@eecs.umich.edu            txState = txDescRead;
21687363Sgblack@eecs.umich.edu            regs.txdp = link;
21697370Sgblack@eecs.umich.edu            CTDD = false;
21707372Sgblack@eecs.umich.edu
21717376Sgblack@eecs.umich.edu            txDmaAddr = link & 0x3fffffff;
21727376Sgblack@eecs.umich.edu            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
21737370Sgblack@eecs.umich.edu            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
21747376Sgblack@eecs.umich.edu            txDmaFree = dmaDescFree;
21757376Sgblack@eecs.umich.edu
21767370Sgblack@eecs.umich.edu            if (doTxDmaRead())
21777370Sgblack@eecs.umich.edu                goto exit;
21787372Sgblack@eecs.umich.edu        }
21797376Sgblack@eecs.umich.edu        break;
21807376Sgblack@eecs.umich.edu
21817370Sgblack@eecs.umich.edu      default:
21827376Sgblack@eecs.umich.edu        panic("invalid state");
21837376Sgblack@eecs.umich.edu    }
21847370Sgblack@eecs.umich.edu
21857370Sgblack@eecs.umich.edu    DPRINTF(EthernetSM, "entering next txState=%s\n",
21867371Sgblack@eecs.umich.edu            NsTxStateStrings[txState]);
21877371Sgblack@eecs.umich.edu    goto next;
21887372Sgblack@eecs.umich.edu
21897376Sgblack@eecs.umich.edu  exit:
21907376Sgblack@eecs.umich.edu    /**
21917371Sgblack@eecs.umich.edu     * @todo do we want to schedule a future kick?
21927376Sgblack@eecs.umich.edu     */
21937376Sgblack@eecs.umich.edu    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
21947371Sgblack@eecs.umich.edu            NsTxStateStrings[txState]);
21957371Sgblack@eecs.umich.edu
21967372Sgblack@eecs.umich.edu    if (clock && !txKickEvent.scheduled())
21977376Sgblack@eecs.umich.edu        txKickEvent.schedule(txKickTick);
21987376Sgblack@eecs.umich.edu}
21997371Sgblack@eecs.umich.edu
22007376Sgblack@eecs.umich.edu/**
22017376Sgblack@eecs.umich.edu * Advance the EEPROM state machine
22027371Sgblack@eecs.umich.edu * Called on rising edge of EEPROM clock bit in MEAR
22037371Sgblack@eecs.umich.edu */
22047363Sgblack@eecs.umich.eduvoid
22057363Sgblack@eecs.umich.eduNSGigE::eepromKick()
22067372Sgblack@eecs.umich.edu{
22077376Sgblack@eecs.umich.edu    switch (eepromState) {
22087376Sgblack@eecs.umich.edu
22097364Sgblack@eecs.umich.edu      case eepromStart:
22107376Sgblack@eecs.umich.edu
22117376Sgblack@eecs.umich.edu        // Wait for start bit
22127364Sgblack@eecs.umich.edu        if (regs.mear & MEAR_EEDI) {
22137371Sgblack@eecs.umich.edu            // Set up to get 2 opcode bits
22147372Sgblack@eecs.umich.edu            eepromState = eepromGetOpcode;
22157376Sgblack@eecs.umich.edu            eepromBitsToRx = 2;
22167376Sgblack@eecs.umich.edu            eepromOpcode = 0;
22177371Sgblack@eecs.umich.edu        }
22187376Sgblack@eecs.umich.edu        break;
22197376Sgblack@eecs.umich.edu
22207371Sgblack@eecs.umich.edu      case eepromGetOpcode:
22217363Sgblack@eecs.umich.edu        eepromOpcode <<= 1;
22227363Sgblack@eecs.umich.edu        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
22237363Sgblack@eecs.umich.edu        --eepromBitsToRx;
22247372Sgblack@eecs.umich.edu
22257376Sgblack@eecs.umich.edu        // Done getting opcode
22267376Sgblack@eecs.umich.edu        if (eepromBitsToRx == 0) {
22277367Sgblack@eecs.umich.edu            if (eepromOpcode != EEPROM_READ)
22287376Sgblack@eecs.umich.edu                panic("only EEPROM reads are implemented!");
22297376Sgblack@eecs.umich.edu
22307367Sgblack@eecs.umich.edu            // Set up to get address
22317363Sgblack@eecs.umich.edu            eepromState = eepromGetAddress;
22327372Sgblack@eecs.umich.edu            eepromBitsToRx = 6;
22337376Sgblack@eecs.umich.edu            eepromAddress = 0;
22347376Sgblack@eecs.umich.edu        }
22357368Sgblack@eecs.umich.edu        break;
22367376Sgblack@eecs.umich.edu
22377376Sgblack@eecs.umich.edu      case eepromGetAddress:
22387368Sgblack@eecs.umich.edu        eepromAddress <<= 1;
22397363Sgblack@eecs.umich.edu        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
22407363Sgblack@eecs.umich.edu        --eepromBitsToRx;
22417363Sgblack@eecs.umich.edu
22427372Sgblack@eecs.umich.edu        // Done getting address
22437376Sgblack@eecs.umich.edu        if (eepromBitsToRx == 0) {
22447376Sgblack@eecs.umich.edu
22457369Sgblack@eecs.umich.edu            if (eepromAddress >= EEPROM_SIZE)
22467376Sgblack@eecs.umich.edu                panic("EEPROM read access out of range!");
22477376Sgblack@eecs.umich.edu
22487369Sgblack@eecs.umich.edu            switch (eepromAddress) {
22497363Sgblack@eecs.umich.edu
22507363Sgblack@eecs.umich.edu              case EEPROM_PMATCH2_ADDR:
22517363Sgblack@eecs.umich.edu                eepromData = rom.perfectMatch[5];
22527363Sgblack@eecs.umich.edu                eepromData <<= 8;
22537363Sgblack@eecs.umich.edu                eepromData += rom.perfectMatch[4];
22547363Sgblack@eecs.umich.edu                break;
22557372Sgblack@eecs.umich.edu
22567363Sgblack@eecs.umich.edu              case EEPROM_PMATCH1_ADDR:
22577376Sgblack@eecs.umich.edu                eepromData = rom.perfectMatch[3];
22587376Sgblack@eecs.umich.edu                eepromData <<= 8;
22597363Sgblack@eecs.umich.edu                eepromData += rom.perfectMatch[2];
22607363Sgblack@eecs.umich.edu                break;
22617376Sgblack@eecs.umich.edu
22627376Sgblack@eecs.umich.edu              case EEPROM_PMATCH0_ADDR:
22637363Sgblack@eecs.umich.edu                eepromData = rom.perfectMatch[1];
22647363Sgblack@eecs.umich.edu                eepromData <<= 8;
22657363Sgblack@eecs.umich.edu                eepromData += rom.perfectMatch[0];
22667363Sgblack@eecs.umich.edu                break;
22677363Sgblack@eecs.umich.edu
22687372Sgblack@eecs.umich.edu              default:
22697376Sgblack@eecs.umich.edu                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
22707376Sgblack@eecs.umich.edu            }
22717363Sgblack@eecs.umich.edu            // Set up to read data
22727376Sgblack@eecs.umich.edu            eepromState = eepromRead;
22737376Sgblack@eecs.umich.edu            eepromBitsToRx = 16;
22747363Sgblack@eecs.umich.edu
22757363Sgblack@eecs.umich.edu            // Clear data in bit
22767372Sgblack@eecs.umich.edu            regs.mear &= ~MEAR_EEDI;
22777376Sgblack@eecs.umich.edu        }
22787376Sgblack@eecs.umich.edu        break;
22797366Sgblack@eecs.umich.edu
22807376Sgblack@eecs.umich.edu      case eepromRead:
22817376Sgblack@eecs.umich.edu        // Clear Data Out bit
22827366Sgblack@eecs.umich.edu        regs.mear &= ~MEAR_EEDO;
22837363Sgblack@eecs.umich.edu        // Set bit to value of current EEPROM bit
22847363Sgblack@eecs.umich.edu        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
22857363Sgblack@eecs.umich.edu
22867372Sgblack@eecs.umich.edu        eepromData <<= 1;
22877376Sgblack@eecs.umich.edu        --eepromBitsToRx;
22887376Sgblack@eecs.umich.edu
22897365Sgblack@eecs.umich.edu        // All done
22907376Sgblack@eecs.umich.edu        if (eepromBitsToRx == 0) {
22917376Sgblack@eecs.umich.edu            eepromState = eepromStart;
22927365Sgblack@eecs.umich.edu        }
22937363Sgblack@eecs.umich.edu        break;
22947372Sgblack@eecs.umich.edu
22957376Sgblack@eecs.umich.edu      default:
22967376Sgblack@eecs.umich.edu        panic("invalid EEPROM state");
22977369Sgblack@eecs.umich.edu    }
22987376Sgblack@eecs.umich.edu
22997376Sgblack@eecs.umich.edu}
23007369Sgblack@eecs.umich.edu
23017363Sgblack@eecs.umich.eduvoid
23027363Sgblack@eecs.umich.eduNSGigE::transferDone()
23037363Sgblack@eecs.umich.edu{
23047398Sgblack@eecs.umich.edu    if (txFifo.empty()) {
23057398Sgblack@eecs.umich.edu        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
23067398Sgblack@eecs.umich.edu        return;
23077398Sgblack@eecs.umich.edu    }
23087398Sgblack@eecs.umich.edu
23097398Sgblack@eecs.umich.edu    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
23107398Sgblack@eecs.umich.edu
23117398Sgblack@eecs.umich.edu    if (txEvent.scheduled())
23127398Sgblack@eecs.umich.edu        txEvent.reschedule(curTick + cycles(1));
23137398Sgblack@eecs.umich.edu    else
23147398Sgblack@eecs.umich.edu        txEvent.schedule(curTick + cycles(1));
23157398Sgblack@eecs.umich.edu}
23167398Sgblack@eecs.umich.edu
23177398Sgblack@eecs.umich.edubool
23187398Sgblack@eecs.umich.eduNSGigE::rxFilter(const EthPacketPtr &packet)
23197398Sgblack@eecs.umich.edu{
23207398Sgblack@eecs.umich.edu    EthPtr eth = packet;
23217363Sgblack@eecs.umich.edu    bool drop = true;
23227377Sgblack@eecs.umich.edu    string type;
23237389Sgblack@eecs.umich.edu
23247389Sgblack@eecs.umich.edu    const EthAddr &dst = eth->dst();
23257389Sgblack@eecs.umich.edu    if (dst.unicast()) {
23267389Sgblack@eecs.umich.edu        // If we're accepting all unicast addresses
23277389Sgblack@eecs.umich.edu        if (acceptUnicast)
23287377Sgblack@eecs.umich.edu            drop = false;
23297389Sgblack@eecs.umich.edu
23307389Sgblack@eecs.umich.edu        // If we make a perfect match
23317389Sgblack@eecs.umich.edu        if (acceptPerfect && dst == rom.perfectMatch)
23327389Sgblack@eecs.umich.edu            drop = false;
23337389Sgblack@eecs.umich.edu
23347377Sgblack@eecs.umich.edu        if (acceptArp && eth->type() == ETH_TYPE_ARP)
23357363Sgblack@eecs.umich.edu            drop = false;
23367377Sgblack@eecs.umich.edu
23377389Sgblack@eecs.umich.edu    } else if (dst.broadcast()) {
23387389Sgblack@eecs.umich.edu        // if we're accepting broadcasts
23397389Sgblack@eecs.umich.edu        if (acceptBroadcast)
23407389Sgblack@eecs.umich.edu            drop = false;
23417389Sgblack@eecs.umich.edu
23427377Sgblack@eecs.umich.edu    } else if (dst.multicast()) {
23437389Sgblack@eecs.umich.edu        // if we're accepting all multicasts
23447389Sgblack@eecs.umich.edu        if (acceptMulticast)
23457389Sgblack@eecs.umich.edu            drop = false;
23467389Sgblack@eecs.umich.edu
23477389Sgblack@eecs.umich.edu        // Multicast hashing faked - all packets accepted
23487377Sgblack@eecs.umich.edu        if (multicastHashEnable)
23497363Sgblack@eecs.umich.edu            drop = false;
23507363Sgblack@eecs.umich.edu    }
23517374Sgblack@eecs.umich.edu
23528270SAli.Saidi@ARM.com    if (drop) {
23538270SAli.Saidi@ARM.com        DPRINTF(Ethernet, "rxFilter drop\n");
23547374Sgblack@eecs.umich.edu        DDUMP(EthernetData, packet->data, packet->length);
23557374Sgblack@eecs.umich.edu    }
23567374Sgblack@eecs.umich.edu
23577374Sgblack@eecs.umich.edu    return drop;
23587374Sgblack@eecs.umich.edu}
23597374Sgblack@eecs.umich.edu
23607363Sgblack@eecs.umich.edubool
23617363Sgblack@eecs.umich.eduNSGigE::recvPacket(EthPacketPtr packet)
23627363Sgblack@eecs.umich.edu{
23637373Sgblack@eecs.umich.edu    rxBytes += packet->length;
23647373Sgblack@eecs.umich.edu    rxPackets++;
23657373Sgblack@eecs.umich.edu
23667373Sgblack@eecs.umich.edu    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
23677373Sgblack@eecs.umich.edu            rxFifo.avail());
23687373Sgblack@eecs.umich.edu
23697373Sgblack@eecs.umich.edu    if (!rxEnable) {
23707373Sgblack@eecs.umich.edu        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
23717373Sgblack@eecs.umich.edu        return true;
23727373Sgblack@eecs.umich.edu    }
23737373Sgblack@eecs.umich.edu
23747373Sgblack@eecs.umich.edu    if (!rxFilterEnable) {
23757373Sgblack@eecs.umich.edu        DPRINTF(Ethernet,
23767373Sgblack@eecs.umich.edu            "receive packet filtering disabled . . . packet dropped\n");
23777373Sgblack@eecs.umich.edu        return true;
23787373Sgblack@eecs.umich.edu    }
23797373Sgblack@eecs.umich.edu
23807363Sgblack@eecs.umich.edu    if (rxFilter(packet)) {
23817379Sgblack@eecs.umich.edu        DPRINTF(Ethernet, "packet filtered...dropped\n");
23827379Sgblack@eecs.umich.edu        return true;
23837379Sgblack@eecs.umich.edu    }
23847379Sgblack@eecs.umich.edu
23857379Sgblack@eecs.umich.edu    if (rxFifo.avail() < packet->length) {
23867379Sgblack@eecs.umich.edu#if TRACING_ON
23877379Sgblack@eecs.umich.edu        IpPtr ip(packet);
23887379Sgblack@eecs.umich.edu        TcpPtr tcp(ip);
23897379Sgblack@eecs.umich.edu        if (ip) {
23907379Sgblack@eecs.umich.edu            DPRINTF(Ethernet,
23917379Sgblack@eecs.umich.edu                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
23927379Sgblack@eecs.umich.edu                    ip->id());
23937379Sgblack@eecs.umich.edu            if (tcp) {
23947379Sgblack@eecs.umich.edu                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
23957379Sgblack@eecs.umich.edu            }
23967379Sgblack@eecs.umich.edu        }
23977379Sgblack@eecs.umich.edu#endif
23987379Sgblack@eecs.umich.edu        droppedPackets++;
23997379Sgblack@eecs.umich.edu        devIntrPost(ISR_RXORN);
24007379Sgblack@eecs.umich.edu        return false;
24017363Sgblack@eecs.umich.edu    }
24027379Sgblack@eecs.umich.edu
24037379Sgblack@eecs.umich.edu    rxFifo.push(packet);
24047379Sgblack@eecs.umich.edu
24057379Sgblack@eecs.umich.edu    rxKick();
24067379Sgblack@eecs.umich.edu    return true;
24077379Sgblack@eecs.umich.edu}
24087379Sgblack@eecs.umich.edu
24097379Sgblack@eecs.umich.edu//=====================================================================
24107379Sgblack@eecs.umich.edu//
24117379Sgblack@eecs.umich.edu//
24127379Sgblack@eecs.umich.eduvoid
24137379Sgblack@eecs.umich.eduNSGigE::serialize(ostream &os)
24147379Sgblack@eecs.umich.edu{
24157379Sgblack@eecs.umich.edu    // Serialize the PciDev base class
24167379Sgblack@eecs.umich.edu    PciDev::serialize(os);
24177379Sgblack@eecs.umich.edu
24187379Sgblack@eecs.umich.edu    /*
24197379Sgblack@eecs.umich.edu     * Finalize any DMA events now.
24207379Sgblack@eecs.umich.edu     */
24217379Sgblack@eecs.umich.edu    // @todo will mem system save pending dma?
24227363Sgblack@eecs.umich.edu
24237380Sgblack@eecs.umich.edu    /*
24247380Sgblack@eecs.umich.edu     * Serialize the device registers
24257380Sgblack@eecs.umich.edu     */
24267380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.command);
24277380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.config);
24287380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.mear);
24297380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.ptscr);
24307380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.isr);
24317373Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.imr);
24327380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.ier);
24337380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.ihr);
24347380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.txdp);
24357380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.txdp_hi);
24367380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.txcfg);
24377380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.gpior);
24387380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.rxdp);
24397373Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.rxdp_hi);
24407363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.rxcfg);
24417380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.pqcr);
24427380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.wcsr);
24437380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.pcr);
24447380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.rfcr);
24457380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.rfdr);
24467380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.brar);
24477380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.brdr);
24487380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.srr);
24497373Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.mibc);
24507380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.vrcr);
24517380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.vtcr);
24527380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.vdr);
24537380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.ccsr);
24547380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.tbicr);
24557380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.tbisr);
24567380Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.tanar);
24577373Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.tanlpar);
24587363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.taner);
24597379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(regs.tesr);
24607379Sgblack@eecs.umich.edu
24617379Sgblack@eecs.umich.edu    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
24627379Sgblack@eecs.umich.edu    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
24637379Sgblack@eecs.umich.edu
24647379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(ioEnable);
24657379Sgblack@eecs.umich.edu
24667379Sgblack@eecs.umich.edu    /*
24677379Sgblack@eecs.umich.edu     * Serialize the data Fifos
24687379Sgblack@eecs.umich.edu     */
24697379Sgblack@eecs.umich.edu    rxFifo.serialize("rxFifo", os);
24707379Sgblack@eecs.umich.edu    txFifo.serialize("txFifo", os);
24717379Sgblack@eecs.umich.edu
24727379Sgblack@eecs.umich.edu    /*
24737379Sgblack@eecs.umich.edu     * Serialize the various helper variables
24747379Sgblack@eecs.umich.edu     */
24757379Sgblack@eecs.umich.edu    bool txPacketExists = txPacket;
24767379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txPacketExists);
24777379Sgblack@eecs.umich.edu    if (txPacketExists) {
24787379Sgblack@eecs.umich.edu        txPacket->length = txPacketBufPtr - txPacket->data;
24797363Sgblack@eecs.umich.edu        txPacket->serialize("txPacket", os);
24807379Sgblack@eecs.umich.edu        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
24817379Sgblack@eecs.umich.edu        SERIALIZE_SCALAR(txPktBufPtr);
24827379Sgblack@eecs.umich.edu    }
24837379Sgblack@eecs.umich.edu
24847379Sgblack@eecs.umich.edu    bool rxPacketExists = rxPacket;
24857379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxPacketExists);
24867379Sgblack@eecs.umich.edu    if (rxPacketExists) {
24877379Sgblack@eecs.umich.edu        rxPacket->serialize("rxPacket", os);
24887379Sgblack@eecs.umich.edu        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
24897379Sgblack@eecs.umich.edu        SERIALIZE_SCALAR(rxPktBufPtr);
24907379Sgblack@eecs.umich.edu    }
24917379Sgblack@eecs.umich.edu
24927379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txXferLen);
24937379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxXferLen);
24947379Sgblack@eecs.umich.edu
24957379Sgblack@eecs.umich.edu    /*
24967379Sgblack@eecs.umich.edu     * Serialize Cached Descriptors
24977379Sgblack@eecs.umich.edu     */
24987379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc64.link);
24997379Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc64.bufptr);
25007363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc64.cmdsts);
25017363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc64.extsts);
25027363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc64.link);
25037363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc64.bufptr);
25047363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc64.cmdsts);
25057363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc64.extsts);
25067363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc32.link);
25077363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc32.bufptr);
25087363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc32.cmdsts);
25097363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(rxDesc32.extsts);
25107363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc32.link);
25117363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc32.bufptr);
25127363Sgblack@eecs.umich.edu    SERIALIZE_SCALAR(txDesc32.cmdsts);
2513    SERIALIZE_SCALAR(txDesc32.extsts);
2514    SERIALIZE_SCALAR(extstsEnable);
2515
2516    /*
2517     * Serialize tx state machine
2518     */
2519    int txState = this->txState;
2520    SERIALIZE_SCALAR(txState);
2521    SERIALIZE_SCALAR(txEnable);
2522    SERIALIZE_SCALAR(CTDD);
2523    SERIALIZE_SCALAR(txFragPtr);
2524    SERIALIZE_SCALAR(txDescCnt);
2525    int txDmaState = this->txDmaState;
2526    SERIALIZE_SCALAR(txDmaState);
2527    SERIALIZE_SCALAR(txKickTick);
2528
2529    /*
2530     * Serialize rx state machine
2531     */
2532    int rxState = this->rxState;
2533    SERIALIZE_SCALAR(rxState);
2534    SERIALIZE_SCALAR(rxEnable);
2535    SERIALIZE_SCALAR(CRDD);
2536    SERIALIZE_SCALAR(rxPktBytes);
2537    SERIALIZE_SCALAR(rxFragPtr);
2538    SERIALIZE_SCALAR(rxDescCnt);
2539    int rxDmaState = this->rxDmaState;
2540    SERIALIZE_SCALAR(rxDmaState);
2541    SERIALIZE_SCALAR(rxKickTick);
2542
2543    /*
2544     * Serialize EEPROM state machine
2545     */
2546    int eepromState = this->eepromState;
2547    SERIALIZE_SCALAR(eepromState);
2548    SERIALIZE_SCALAR(eepromClk);
2549    SERIALIZE_SCALAR(eepromBitsToRx);
2550    SERIALIZE_SCALAR(eepromOpcode);
2551    SERIALIZE_SCALAR(eepromAddress);
2552    SERIALIZE_SCALAR(eepromData);
2553
2554    /*
2555     * If there's a pending transmit, store the time so we can
2556     * reschedule it later
2557     */
2558    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
2559    SERIALIZE_SCALAR(transmitTick);
2560
2561    /*
2562     * receive address filter settings
2563     */
2564    SERIALIZE_SCALAR(rxFilterEnable);
2565    SERIALIZE_SCALAR(acceptBroadcast);
2566    SERIALIZE_SCALAR(acceptMulticast);
2567    SERIALIZE_SCALAR(acceptUnicast);
2568    SERIALIZE_SCALAR(acceptPerfect);
2569    SERIALIZE_SCALAR(acceptArp);
2570    SERIALIZE_SCALAR(multicastHashEnable);
2571
2572    /*
2573     * Keep track of pending interrupt status.
2574     */
2575    SERIALIZE_SCALAR(intrTick);
2576    SERIALIZE_SCALAR(cpuPendingIntr);
2577    Tick intrEventTick = 0;
2578    if (intrEvent)
2579        intrEventTick = intrEvent->when();
2580    SERIALIZE_SCALAR(intrEventTick);
2581
2582}
2583
2584void
2585NSGigE::unserialize(Checkpoint *cp, const std::string &section)
2586{
2587    // Unserialize the PciDev base class
2588    PciDev::unserialize(cp, section);
2589
2590    UNSERIALIZE_SCALAR(regs.command);
2591    UNSERIALIZE_SCALAR(regs.config);
2592    UNSERIALIZE_SCALAR(regs.mear);
2593    UNSERIALIZE_SCALAR(regs.ptscr);
2594    UNSERIALIZE_SCALAR(regs.isr);
2595    UNSERIALIZE_SCALAR(regs.imr);
2596    UNSERIALIZE_SCALAR(regs.ier);
2597    UNSERIALIZE_SCALAR(regs.ihr);
2598    UNSERIALIZE_SCALAR(regs.txdp);
2599    UNSERIALIZE_SCALAR(regs.txdp_hi);
2600    UNSERIALIZE_SCALAR(regs.txcfg);
2601    UNSERIALIZE_SCALAR(regs.gpior);
2602    UNSERIALIZE_SCALAR(regs.rxdp);
2603    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2604    UNSERIALIZE_SCALAR(regs.rxcfg);
2605    UNSERIALIZE_SCALAR(regs.pqcr);
2606    UNSERIALIZE_SCALAR(regs.wcsr);
2607    UNSERIALIZE_SCALAR(regs.pcr);
2608    UNSERIALIZE_SCALAR(regs.rfcr);
2609    UNSERIALIZE_SCALAR(regs.rfdr);
2610    UNSERIALIZE_SCALAR(regs.brar);
2611    UNSERIALIZE_SCALAR(regs.brdr);
2612    UNSERIALIZE_SCALAR(regs.srr);
2613    UNSERIALIZE_SCALAR(regs.mibc);
2614    UNSERIALIZE_SCALAR(regs.vrcr);
2615    UNSERIALIZE_SCALAR(regs.vtcr);
2616    UNSERIALIZE_SCALAR(regs.vdr);
2617    UNSERIALIZE_SCALAR(regs.ccsr);
2618    UNSERIALIZE_SCALAR(regs.tbicr);
2619    UNSERIALIZE_SCALAR(regs.tbisr);
2620    UNSERIALIZE_SCALAR(regs.tanar);
2621    UNSERIALIZE_SCALAR(regs.tanlpar);
2622    UNSERIALIZE_SCALAR(regs.taner);
2623    UNSERIALIZE_SCALAR(regs.tesr);
2624
2625    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2626    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2627
2628    UNSERIALIZE_SCALAR(ioEnable);
2629
2630    /*
2631     * unserialize the data fifos
2632     */
2633    rxFifo.unserialize("rxFifo", cp, section);
2634    txFifo.unserialize("txFifo", cp, section);
2635
2636    /*
2637     * unserialize the various helper variables
2638     */
2639    bool txPacketExists;
2640    UNSERIALIZE_SCALAR(txPacketExists);
2641    if (txPacketExists) {
2642        txPacket = new EthPacketData(16384);
2643        txPacket->unserialize("txPacket", cp, section);
2644        uint32_t txPktBufPtr;
2645        UNSERIALIZE_SCALAR(txPktBufPtr);
2646        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2647    } else
2648        txPacket = 0;
2649
2650    bool rxPacketExists;
2651    UNSERIALIZE_SCALAR(rxPacketExists);
2652    rxPacket = 0;
2653    if (rxPacketExists) {
2654        rxPacket = new EthPacketData(16384);
2655        rxPacket->unserialize("rxPacket", cp, section);
2656        uint32_t rxPktBufPtr;
2657        UNSERIALIZE_SCALAR(rxPktBufPtr);
2658        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2659    } else
2660        rxPacket = 0;
2661
2662    UNSERIALIZE_SCALAR(txXferLen);
2663    UNSERIALIZE_SCALAR(rxXferLen);
2664
2665    /*
2666     * Unserialize Cached Descriptors
2667     */
2668    UNSERIALIZE_SCALAR(rxDesc64.link);
2669    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2670    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2671    UNSERIALIZE_SCALAR(rxDesc64.extsts);
2672    UNSERIALIZE_SCALAR(txDesc64.link);
2673    UNSERIALIZE_SCALAR(txDesc64.bufptr);
2674    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2675    UNSERIALIZE_SCALAR(txDesc64.extsts);
2676    UNSERIALIZE_SCALAR(rxDesc32.link);
2677    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2678    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2679    UNSERIALIZE_SCALAR(rxDesc32.extsts);
2680    UNSERIALIZE_SCALAR(txDesc32.link);
2681    UNSERIALIZE_SCALAR(txDesc32.bufptr);
2682    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2683    UNSERIALIZE_SCALAR(txDesc32.extsts);
2684    UNSERIALIZE_SCALAR(extstsEnable);
2685
2686    /*
2687     * unserialize tx state machine
2688     */
2689    int txState;
2690    UNSERIALIZE_SCALAR(txState);
2691    this->txState = (TxState) txState;
2692    UNSERIALIZE_SCALAR(txEnable);
2693    UNSERIALIZE_SCALAR(CTDD);
2694    UNSERIALIZE_SCALAR(txFragPtr);
2695    UNSERIALIZE_SCALAR(txDescCnt);
2696    int txDmaState;
2697    UNSERIALIZE_SCALAR(txDmaState);
2698    this->txDmaState = (DmaState) txDmaState;
2699    UNSERIALIZE_SCALAR(txKickTick);
2700    if (txKickTick)
2701        txKickEvent.schedule(txKickTick);
2702
2703    /*
2704     * unserialize rx state machine
2705     */
2706    int rxState;
2707    UNSERIALIZE_SCALAR(rxState);
2708    this->rxState = (RxState) rxState;
2709    UNSERIALIZE_SCALAR(rxEnable);
2710    UNSERIALIZE_SCALAR(CRDD);
2711    UNSERIALIZE_SCALAR(rxPktBytes);
2712    UNSERIALIZE_SCALAR(rxFragPtr);
2713    UNSERIALIZE_SCALAR(rxDescCnt);
2714    int rxDmaState;
2715    UNSERIALIZE_SCALAR(rxDmaState);
2716    this->rxDmaState = (DmaState) rxDmaState;
2717    UNSERIALIZE_SCALAR(rxKickTick);
2718    if (rxKickTick)
2719        rxKickEvent.schedule(rxKickTick);
2720
2721    /*
2722     * Unserialize EEPROM state machine
2723     */
2724    int eepromState;
2725    UNSERIALIZE_SCALAR(eepromState);
2726    this->eepromState = (EEPROMState) eepromState;
2727    UNSERIALIZE_SCALAR(eepromClk);
2728    UNSERIALIZE_SCALAR(eepromBitsToRx);
2729    UNSERIALIZE_SCALAR(eepromOpcode);
2730    UNSERIALIZE_SCALAR(eepromAddress);
2731    UNSERIALIZE_SCALAR(eepromData);
2732
2733    /*
2734     * If there's a pending transmit, reschedule it now
2735     */
2736    Tick transmitTick;
2737    UNSERIALIZE_SCALAR(transmitTick);
2738    if (transmitTick)
2739        txEvent.schedule(curTick + transmitTick);
2740
2741    /*
2742     * unserialize receive address filter settings
2743     */
2744    UNSERIALIZE_SCALAR(rxFilterEnable);
2745    UNSERIALIZE_SCALAR(acceptBroadcast);
2746    UNSERIALIZE_SCALAR(acceptMulticast);
2747    UNSERIALIZE_SCALAR(acceptUnicast);
2748    UNSERIALIZE_SCALAR(acceptPerfect);
2749    UNSERIALIZE_SCALAR(acceptArp);
2750    UNSERIALIZE_SCALAR(multicastHashEnable);
2751
2752    /*
2753     * Keep track of pending interrupt status.
2754     */
2755    UNSERIALIZE_SCALAR(intrTick);
2756    UNSERIALIZE_SCALAR(cpuPendingIntr);
2757    Tick intrEventTick;
2758    UNSERIALIZE_SCALAR(intrEventTick);
2759    if (intrEventTick) {
2760        intrEvent = new IntrEvent(this, true);
2761        intrEvent->schedule(intrEventTick);
2762    }
2763}
2764
2765BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2766
2767    SimObjectParam<EtherInt *> peer;
2768    SimObjectParam<NSGigE *> device;
2769
2770END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2771
2772BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2773
2774    INIT_PARAM_DFLT(peer, "peer interface", NULL),
2775    INIT_PARAM(device, "Ethernet device of this interface")
2776
2777END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2778
2779CREATE_SIM_OBJECT(NSGigEInt)
2780{
2781    NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
2782
2783    EtherInt *p = (EtherInt *)peer;
2784    if (p) {
2785        dev_int->setPeer(p);
2786        p->setPeer(dev_int);
2787    }
2788
2789    return dev_int;
2790}
2791
2792REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
2793
2794
2795BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2796
2797    SimObjectParam<System *> system;
2798    SimObjectParam<Platform *> platform;
2799    SimObjectParam<PciConfigData *> configdata;
2800    Param<uint32_t> pci_bus;
2801    Param<uint32_t> pci_dev;
2802    Param<uint32_t> pci_func;
2803    Param<Tick> pio_latency;
2804
2805    Param<Tick> clock;
2806    Param<bool> dma_desc_free;
2807    Param<bool> dma_data_free;
2808    Param<Tick> dma_read_delay;
2809    Param<Tick> dma_write_delay;
2810    Param<Tick> dma_read_factor;
2811    Param<Tick> dma_write_factor;
2812    Param<bool> dma_no_allocate;
2813    Param<Tick> intr_delay;
2814
2815    Param<Tick> rx_delay;
2816    Param<Tick> tx_delay;
2817    Param<uint32_t> rx_fifo_size;
2818    Param<uint32_t> tx_fifo_size;
2819
2820    Param<bool> rx_filter;
2821    Param<string> hardware_address;
2822    Param<bool> rx_thread;
2823    Param<bool> tx_thread;
2824    Param<bool> rss;
2825
2826END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2827
2828BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
2829
2830    INIT_PARAM(system, "System pointer"),
2831    INIT_PARAM(platform, "Platform pointer"),
2832    INIT_PARAM(configdata, "PCI Config data"),
2833    INIT_PARAM(pci_bus, "PCI bus ID"),
2834    INIT_PARAM(pci_dev, "PCI device number"),
2835    INIT_PARAM(pci_func, "PCI function code"),
2836    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
2837    INIT_PARAM(clock, "State machine cycle time"),
2838
2839    INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"),
2840    INIT_PARAM(dma_data_free, "DMA of Data is free"),
2841    INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
2842    INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
2843    INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
2844    INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
2845    INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"),
2846    INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
2847
2848    INIT_PARAM(rx_delay, "Receive Delay"),
2849    INIT_PARAM(tx_delay, "Transmit Delay"),
2850    INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
2851    INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
2852
2853    INIT_PARAM(rx_filter, "Enable Receive Filter"),
2854    INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
2855    INIT_PARAM(rx_thread, ""),
2856    INIT_PARAM(tx_thread, ""),
2857    INIT_PARAM(rss, "")
2858
2859END_INIT_SIM_OBJECT_PARAMS(NSGigE)
2860
2861
2862CREATE_SIM_OBJECT(NSGigE)
2863{
2864    NSGigE::Params *params = new NSGigE::Params;
2865
2866    params->name = getInstanceName();
2867    params->platform = platform;
2868    params->system = system;
2869    params->configData = configdata;
2870    params->busNum = pci_bus;
2871    params->deviceNum = pci_dev;
2872    params->functionNum = pci_func;
2873    params->pio_delay = pio_latency;
2874
2875    params->clock = clock;
2876    params->dma_desc_free = dma_desc_free;
2877    params->dma_data_free = dma_data_free;
2878    params->dma_read_delay = dma_read_delay;
2879    params->dma_write_delay = dma_write_delay;
2880    params->dma_read_factor = dma_read_factor;
2881    params->dma_write_factor = dma_write_factor;
2882    params->dma_no_allocate = dma_no_allocate;
2883    params->pio_delay = pio_latency;
2884    params->intr_delay = intr_delay;
2885
2886    params->rx_delay = rx_delay;
2887    params->tx_delay = tx_delay;
2888    params->rx_fifo_size = rx_fifo_size;
2889    params->tx_fifo_size = tx_fifo_size;
2890
2891    params->rx_filter = rx_filter;
2892    params->eaddr = hardware_address;
2893    params->rx_thread = rx_thread;
2894    params->tx_thread = tx_thread;
2895    params->rss = rss;
2896
2897    return new NSGigE(params);
2898}
2899
2900REGISTER_SIM_OBJECT("NSGigE", NSGigE)
2901